Presentation is loading. Please wait.

Presentation is loading. Please wait.

Common SQL Programming Mistakes.

Similar presentations


Presentation on theme: "Common SQL Programming Mistakes."— Presentation transcript:

1 Common SQL Programming Mistakes

2 Who am I?? Kevin G. Boles SQL Server Consultant “The Wolfe” for the Relational Engine Indicium Resources, Inc. AIM/Twitter: TheSQLGuru Gtalk/GMail: MCITP, MCT, MVP , yada-yada

3 What do I do? World-class Better than average relational engine expert  Almost 45,000 man-hours invested in SQL Server Absolutely LOVE doing targeted performance analysis and tuning work VERY good at making others better at interacting with SQL Server Couldn’t SSAS my way out of a paper bag … with both ends open! 

4 Why learn from others mistakes?
Smart people Learn from their mistakes. Wise people Learn from other peoples mistakes.

5 Agenda Why do we make these mistakes? Common SQL programming mistakes:
NULLs and the NOT IN predicate Functions on indexed columns in predicates Incorrect subquery column Data type mismatch in predicates Predicate evaluation order Outer joins and placement of predicates Subqueries that return more than one value Use of SELECT * Scalar user-defined functions Overuse of cursors Triggers Other mistakes

6 Why do we make these mistakes?
Coming from different background (Java, C, C++, etc.) Inherited responsibilities Learning the wrong way (or from incorrect sources) Bad practices in team collaboration Incorrect design Not testing exception cases Overworking (not enough caffeine) On the wrong bus Never engaged TheSQLGuru as a consultant/mentor!! 

7 NULLs and the NOT IN predicate
/* Colors: color Black Blue Green Red Products: sku product_description color 1 Ball Red 2 Bike Blue 3 Tent NULL */ SELECT C.color FROM Colors AS C WHERE C.color NOT IN (SELECT P.color FROM Products AS P);

8 Functions on indexed columns in predicates
SELECT customer_name FROM Customers WHERE LEFT(customer_name, 1) = 'L'; SELECT SUM(sale_amount) AS total_sales FROM Sales WHERE DATEPART(YEAR, sale_date) = 2009 AND DATEPART(MONTH, sale_date) = 1; /* Exception: SQL Server */ WHERE CAST(sale_date AS DATE) = ' ';

9 Incorrect subquery column
/* Left to the inquisitive attendee  ALWAYS USE ALIASES FOR EVERYTHING!! Sales: sale_date sale_amount Calendar: calendar_date holiday_name New Year's Day NULL NULL NULL NULL */ SELECT sale_date, sale_amount FROM Sales AS S WHERE sale_date IN (SELECT sale_date FROM Calendar AS C WHERE holiday_name IS NOT NULL);

10 Data type mismatch in predicates
CREATE TABLE Customers ( customer_nbr INT NOT NULL PRIMARY KEY, first_name VARCHAR(35) NOT NULL, last_name VARCHAR(35) NOT NULL); SELECT first_name, last_name FROM Customers WHERE last_name = N'Brown'; /* StmtText |--Clustered Index Scan(OBJECT:( [dbo].[Customers].[PK_Customer]), WHERE:(CONVERT_IMPLICIT(nvarchar(35), */

11 Data type mismatch in predicates (solution)
SELECT first_name, last_name FROM Customers WHERE last_name = 'Brown'; BEWARE calling application for this. Some connection mechanisms if you use defaults (ADO.NET) will declare vars sent to SQL Server as Nvarchar. I just came across 3rd party app that did this and got order of magnitude plus performance gain across the board and HUGE increases in concurrency from explicitly declaring proper datatypes in data access layer!!!

12 Predicate evaluation order
/* Accounts: account_nbr account_type account_reference Personal abc Business Basic 101 Personal def Business Plus 5 */ SELECT account_nbr, account_reference AS account_ref_nbr FROM Accounts WHERE account_type LIKE 'Business%' AND CAST(account_reference AS INT) > 20; SELECT account_nbr, account_ref_nbr FROM (SELECT account_nbr, CAST(account_reference AS INT) AS account_ref_nbr WHERE account_type LIKE 'Business%') AS A WHERE account_ref_nbr > 20;

13 Outer joins and placement of predicates
SELECT C.customer_name, SUM(COALESCE(O.order_amt, 0)) AS total_2009 FROM Customers AS C LEFT OUTER JOIN Orders AS O ON C.customer_nbr = O.customer_nbr WHERE O.order_date >= ' ' GROUP BY C.customer_name; SELECT C.customer_name, O.order_amt, D.qty INNER JOIN OrderDetails AS D ON D.order_nbr = O.order_nbr AND D.sku = 101;

14 Subqueries that return more than one value -- Left to the inquisitive attendee 
SELECT sku, product_description, (SELECT plant_nbr FROM ProductPlants AS B WHERE B.sku = A.sku) AS plant_nbr FROM Products AS A; SELECT A.sku, A.product_description, B.plant_nbr FROM Products AS A JOIN ProductPlants AS B ON A.sku = B.sku WHERE B.sku = (SELECT C.sku FROM NewProducts AS C WHERE C.product_description LIKE '%guitar%');

15 Use of SELECT. ALWAYS use explicit column names
Use of SELECT * ALWAYS use explicit column names! Easy with code generators now! Talk on view error, show performance issue INSERT INTO PlasticProducts SELECT * FROM Products WHERE material_type = 'plastic'; CREATE VIEW MetalProducts AS WHERE material_type = 'metal';

16 Scalar user-defined functions
CREATE FUNCTION [dbo].[fn_TotalPrice] int) RETURNS money WITH SCHEMABINDING AS BEGIN money = SUM(UnitPrice * Quantity) FROM dbo.[Order Details] WHERE OrderID END

17 Overuse of cursors (and WHILE, recursive CTEs)
/* Left to the inquisitive attendee :) almost NEVER a need for these – running totals maybe (DENALI WIN!!) */ DECLARE PriceUpdates CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY FOR SELECT sku, price FROM NewPrices; OPEN PriceUpdates; FETCH NEXT FROM PriceUpdates @price; WHILE = 0 BEGIN UPDATE ProductPrices SET price effective_start_date = CURRENT_TIMESTAMP WHERE sku END

18 Triggers and Multiple Rows
Triggers do NOT fire once per row!! Body of trigger: varchar(10) = = myChar FROM INSERTED INSERT AuditTable

19 IS NULL OR BADNESS CREATE PROC badIsNULLORProc int) AS SET NOCOUNT ON SELECT a, b, c FROM dbo.KGBIsNULLORTest WHERE = a IS NULL) AND = b IS NULL) RETURN

20 Other mistakes SQL-89 vs. SLQ-92 join syntax Date ranges Date formats
Missing correlation in subqueries Data type precedence in expressions Integer division MONEY vs. DECIMAL/float (big deal in large DWs) Declaring VARCHAR without length Division by zero handling “Ordered” views NULL does not equal NULL or other values Nondeterministic updates Dynamic searches Arithmetic operator precedence Other…

21 Questions and comments
The trouble with people is not that they don't know but that they know so much that ain't so. Josh Billings Kevin G. Boles @TheSQLGuru Slide Deck by: Plamen Ratchev blog :


Download ppt "Common SQL Programming Mistakes."

Similar presentations


Ads by Google