Presentation is loading. Please wait.

Presentation is loading. Please wait.

Common SQL Programming Mistakes. Sponsors Who am I?? Kevin G. Boles SQL Server Consultant “The Wolf” for the Relational Engine Indicium Resources, Inc.

Similar presentations


Presentation on theme: "Common SQL Programming Mistakes. Sponsors Who am I?? Kevin G. Boles SQL Server Consultant “The Wolf” for the Relational Engine Indicium Resources, Inc."— Presentation transcript:

1 Common SQL Programming Mistakes

2 Sponsors

3 Who am I?? Kevin G. Boles SQL Server Consultant “The Wolf” for the Relational Engine Indicium Resources, Inc. AIM/Twitter: TheSQLGuru Gtalk/GMail: TheSQLGuru@gmail.comTheSQLGuru@gmail.com MCITP, MCT, MVP 2007-2012, yada-yada

4 What do I do?  World-class relational engine expert  Almost 40,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!

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

6 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

7 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!!

8 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);

9 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 2008+ */ SELECT SUM(sale_amount) AS total_sales FROM Sales WHERE CAST(sale_date AS DATE) = '20090101';

10 Incorrect subquery column /* Left to the inquisitive attendee ALWAYS USE ALIASES FOR EVERYTHING!! Sales: sale_date sale_amount ---------- ----------- 2009-01-01 120.50 2009-01-02 115.00 Calendar: calendar_date holiday_name ------------- --------------- 2009-01-01 New Year's Day 2009-01-02 NULL 2009-01-03 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);

11 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), [dbo].[Customers].[last_name],0)=[@1])) */

12 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 3 rd 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!!!

13 Predicate evaluation order /* Accounts: account_nbr account_type account_reference ----------- --------------- ----------------- 1 Personal abc 2 Business Basic 101 3 Personal def 4 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 FROM Accounts WHERE account_type LIKE 'Business%') AS A WHERE account_ref_nbr > 20;

14 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 >= '20090101' GROUP BY C.customer_name; SELECT C.customer_name, O.order_amt, D.qty FROM Customers AS C LEFT OUTER JOIN Orders AS O ON C.customer_nbr = O.customer_nbr INNER JOIN OrderDetails AS D ON D.order_nbr = O.order_nbr AND D.sku = 101;

15 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%');

16 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 SELECT * FROM Products WHERE material_type = 'metal';

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

18 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 INTO @sku, @price; WHILE @@FETCH_STATUS = 0 BEGIN UPDATE ProductPrices SET price = @price, effective_start_date = CURRENT_TIMESTAMP WHERE sku = @sku; FETCH NEXT FROM PriceUpdates INTO @sku, @price; END

19 Triggers and Multiple Rows Triggers do NOT fire once per row!! Body of trigger: DECLARE @id int, @myChar varchar(10) SELECT @id = ID, @myChar = myChar FROM INSERTED INSERT AuditTable VALUES (@id, @myChar)

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

21 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  Nondeterministic updates  Dynamic searches  Arithmetic operator precedence  Other…

22 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@gmail.com @TheSQLGuru Slide Deck by: Plamen Ratchev e-mail: plamen@tangrainc.com blog : http://pratchev.blogspot.com

23 Sponsors


Download ppt "Common SQL Programming Mistakes. Sponsors Who am I?? Kevin G. Boles SQL Server Consultant “The Wolf” for the Relational Engine Indicium Resources, Inc."

Similar presentations


Ads by Google