Các mô hình chống SQL phổ biến nhất là gì? [đóng cửa]


232

Tất cả chúng ta làm việc với các cơ sở dữ liệu quan hệ đã học (hoặc đang học) rằng SQL là khác nhau. Lấy kết quả mong muốn và thực hiện một cách hiệu quả, bao gồm một quá trình tẻ nhạt một phần được đặc trưng bằng cách học các mô hình lạ, và phát hiện ra rằng một số mô hình lập trình quen thuộc nhất của chúng ta không hoạt động ở đây. Các antipotype phổ biến bạn đã thấy (hoặc bản thân bạn đã cam kết) là gì?


Đây là một câu hỏi không phù hợp với các tiêu chuẩn mới hơn về loại câu hỏi nào phù hợp với Stack Overflow. Khi được hỏi, điều này có thể không đúng.
David Manheim

@casperOne không có điều khoản "ý nghĩa lịch sử" nào có thể khiến câu hỏi này trở thành sự chấp nhận?
Amy B

26
Tôi thấy buồn khi một trong những câu hỏi hữu ích nhất trên trang wohole bị đóng vì không mang tính xây dựng.
HLGEM

11
@HLGEM Tôi hoàn toàn đồng ý. Câu hỏi này là một ví dụ hoàn hảo cho tất cả những gì sai với StackExchange
Kevin Morse

1
Chủ đề là hoàn toàn quan trọng và có liên quan. Nhưng câu hỏi quá mở, đó là lý do tại sao mỗi câu trả lời mô tả lỗi sửa lỗi cá nhân của một kỹ sư.
Shane

Câu trả lời:


156

Tôi luôn cảm thấy thất vọng bởi hầu hết các lập trình viên có xu hướng trộn logic UI của họ vào lớp truy cập dữ liệu:

SELECT
    FirstName + ' ' + LastName as "Full Name",
    case UserRole
        when 2 then "Admin"
        when 1 then "Moderator"
        else "User"
    end as "User's Role",
    case SignedIn
        when 0 then "Logged in"
        else "Logged out"
    end as "User signed in?",
    Convert(varchar(100), LastSignOn, 101) as "Last Sign On",
    DateDiff('d', LastSignOn, getDate()) as "Days since last sign on",
    AddrLine1 + ' ' + AddrLine2 + ' ' + AddrLine3 + ' ' +
        City + ', ' + State + ' ' + Zip as "Address",
    'XXX-XX-' + Substring(
        Convert(varchar(9), SSN), 6, 4) as "Social Security #"
FROM Users

Thông thường, các lập trình viên làm điều này bởi vì họ có ý định liên kết trực tiếp tập dữ liệu của họ vào lưới và thật tiện lợi khi có máy chủ định dạng SQL Server phía máy chủ hơn định dạng trên máy khách.

Các truy vấn như cái được hiển thị ở trên cực kỳ dễ vỡ vì chúng kết hợp chặt chẽ lớp dữ liệu với lớp UI. Trên hết, phong cách lập trình này ngăn chặn triệt để các thủ tục được lưu trữ không thể tái sử dụng.


10
Một mẫu áp phích con tốt để ghép tối đa trên số lớp trừu tượng / tầng trừu tượng lớn nhất có thể.
dkretz

3
Có thể không tốt cho việc ghép nối, mặc dù vì lý do hiệu suất tôi đã thực hiện những việc như vậy thường xuyên, các thay đổi lặp được thực hiện bởi SQL Server nhanh hơn so với thực hiện bằng mã ở tầng giữa. Tôi không nhận được điểm tái sử dụng - không có gì ngăn bạn chạy SP và đổi tên cols nếu muốn.
Joe Pineda

54
Sở thích của tôi là khi mọi người nhúng HTML VÀ javascript, ví dụ: CHỌN '<a href=... onclick="">' + name '</a>'
Matt Rogish

15
Với các truy vấn như thế này, bạn có thể chỉnh sửa lưới trong trang web bằng một câu lệnh thay đổi đơn giản. Hoặc thay đổi nội dung xuất khẩu, hoặc định dạng lại một ngày trong báo cáo. Điều này làm cho khách hàng hài lòng, và tiết kiệm thời gian cho tôi. Vì vậy, cảm ơn, nhưng không cảm ơn, tôi sẽ gắn bó với các truy vấn như thế này.
Andomar

4
@Matt Rogish - jesus, ai đó thực sự làm điều đó?
Axarydax

118

Dưới đây là top 3 của tôi.

Số 1. Không chỉ định danh sách trường. (Chỉnh sửa: để tránh nhầm lẫn: đây là quy tắc mã sản xuất. Nó không áp dụng cho các tập lệnh phân tích một lần - trừ khi tôi là tác giả.)

SELECT *
Insert Into blah SELECT *

nên là

SELECT fieldlist
Insert Into blah (fieldlist) SELECT fieldlist

Số 2. Sử dụng một con trỏ và vòng lặp while, khi một vòng lặp while có biến vòng lặp sẽ làm.

DECLARE @LoopVar int

SET @LoopVar = (SELECT MIN(TheKey) FROM TheTable)
WHILE @LoopVar is not null
BEGIN
  -- Do Stuff with current value of @LoopVar
  ...
  --Ok, done, now get the next value
  SET @LoopVar = (SELECT MIN(TheKey) FROM TheTable
    WHERE @LoopVar < TheKey)
END

Số 3. DateLogic thông qua các loại chuỗi.

--Trim the time
Convert(Convert(theDate, varchar(10), 121), datetime)

Nên là

--Trim the time
DateAdd(dd, DateDiff(dd, 0, theDate), 0)

Tôi đã thấy một đột biến gần đây của "Một truy vấn tốt hơn hai, đáng kinh ngạc?"

SELECT *
FROM blah
WHERE (blah.Name = @name OR @name is null)
  AND (blah.Purpose = @Purpose OR @Purpose is null)

Truy vấn này yêu cầu hai hoặc ba kế hoạch thực hiện khác nhau tùy thuộc vào các giá trị của các tham số. Chỉ có một kế hoạch thực hiện được tạo và mắc kẹt vào bộ đệm cho văn bản sql này. Kế hoạch đó sẽ được sử dụng bất kể giá trị của các tham số. Điều này dẫn đến hiệu suất kém liên tục. Sẽ tốt hơn nhiều khi viết hai truy vấn (một truy vấn cho mỗi kế hoạch thực hiện dự định).


7
hmmm, tôi sẽ cung cấp cho bạn +1 cho điểm 2 và 3 một mình, nhưng các nhà phát triển vượt qua quy tắc 1. Đôi khi nó có vị trí.
annakata

1
Lý do đằng sau # 1 là gì?
jalf

29
Khi bạn sử dụng select *, bạn sẽ nhận được bất cứ thứ gì trong bảng. Những cột có thể thay đổi tên và thứ tự. Mã khách hàng thường xuyên dựa vào tên và thứ tự. Cứ sau 6 tháng, tôi được hỏi cách giữ trật tự cột khi sửa đổi bảng. Nếu quy tắc được tuân theo nó sẽ không thành vấn đề.
Amy B

Đôi khi tôi đã sử dụng # 2, những người khác tôi đã đi theo con đường (mặc dù trước tiên tôi lưu kết quả của truy vấn trên bảng var, mở con trỏ trên đó). Tôi đã luôn tự hỏi nếu ai đó đã thực hiện một bài kiểm tra hiệu suất của cả hai.
Joe Pineda

4
... nhưng tất nhiên các con trỏ hầu như luôn luôn là giải pháp cuối cùng, sau khi thất bại trong việc tìm ra cách thực hiện công việc với SQL dựa trên tập hợp. Có lần tôi đã dành khoảng 45 phút để phân tích một cách cẩn thận một con trỏ PL / SQL khổng lồ, khủng khiếp trong một thủ tục được lưu trữ (đã vẽ sơ đồ của vật bị thối), trong đó đưa ra một bảng tạm thời lớn sau đó chọn nội dung của bảng tạm thời cho người gọi để hiển thị báo cáo. Phải mất 8,5 phút để chạy, trên phần cứng đáng kể. Sau khi lập sơ đồ toàn bộ, tôi có thể thay thế nó bằng một truy vấn duy nhất trả về kết quả tương tự trong vòng dưới 2 giây. Con trỏ, người đàn ông ...
Craig

71
  • Các trường mật khẩu có thể đọc được của con người , egad. Tự giải thích.

  • Sử dụng THÍCH đối với các cột được lập chỉ mục và tôi gần như muốn nói chung là THÍCH.

  • Tái chế các giá trị PK do SQL tạo.

  • Bất ngờ không ai nhắc đến bàn thần . Không có gì nói "hữu cơ" như 100 cột cờ bit, chuỗi lớn và số nguyên.

  • Sau đó, có mẫu "Tôi nhớ tệp .ini" : lưu trữ CSV, chuỗi được phân tách bằng đường ống hoặc dữ liệu cần thiết khác trong các trường văn bản lớn.

  • Và đối với máy chủ MS SQL, việc sử dụng các con trỏ hoàn toàn . Có một cách tốt hơn để thực hiện bất kỳ tác vụ con trỏ nhất định.

Đã chỉnh sửa vì có rất nhiều!


19
sai về con trỏ, tôi sẽ do dự khi nói làm bất kỳ việc cụ thể nào là đúng 100% hoặc sai 100%
Shawn

4
Cho đến nay, mọi ví dụ bảo vệ con trỏ tôi từng thấy là sử dụng công cụ sai cho công việc. Nhưng nếu tất cả những gì bạn biết là SQL, bạn có thể sử dụng nó không phù hợp hoặc bạn học cách viết các loại phần mềm khác.
dkretz

3
@tuinstoel: Làm thế nào để THÍCH '% blah%' sử dụng một chỉ mục? Lập chỉ mục dựa trên thứ tự và ví dụ này tìm kiếm vị trí giữa ngẫu nhiên của chuỗi. (Sắp xếp thứ tự theo ký tự thứ 1, và vì vậy, nhìn vào 4 ký tự ở giữa sẽ đưa ra thứ tự gần như ngẫu nhiên ...)
MatBailie

12
Trên hầu hết các máy chủ cơ sở dữ liệu (ít nhất là các máy chủ tôi đã sử dụng), THÍCH có thể sử dụng các chỉ mục .. miễn là đó là tìm kiếm tiền tố (THÍCH 'xxx%') - nghĩa là, miễn là các ký tự đại diện không đến đầu tiên trong chuỗi tìm kiếm. Tôi nghĩ rằng bạn có thể đang nói về mục đích chéo ở đây một chút.
Cowan

10
Nó giống như bạn không thích LIKE '%LIKE'.
Johan

62

Đừng đào sâu cho nó: Không sử dụng các tuyên bố đã chuẩn bị.


3
Vâng Theo sát trong cùng một bối cảnh, theo kinh nghiệm của tôi, với "lỗi không bẫy".
dkretz

1
@stesch: Điều này không là gì so với việc sử dụng lượt xem và có ngày báo cáo thay đổi. Lượt xem là một phản mẫu nếu bạn có ngày báo cáo thay đổi (tôi giả sử hầu hết các ứng dụng đều có). Sẽ thêm điều này trong một câu trả lời riêng biệt, nhưng nó không may bị đóng.
Stefan Steiger

56

Sử dụng bí danh bảng vô nghĩa:

from employee t1,
department t2,
job t3,
...

Làm cho việc đọc một câu lệnh SQL lớn trở nên khó hơn nhiều so với yêu cầu


49
bí danh? địa ngục Tôi đã thấy tên cột thực tế như thế
annakata

10
bí danh terse là OKAY. Nếu bạn muốn một cái tên có ý nghĩa thì đừng sử dụng bí danh nào cả.
Joel Coehoorn

43
Anh không nói "ngắn gọn", anh nói "vô nghĩa". Trong cuốn sách của tôi, sẽ không có gì sai khi sử dụng e, d và j làm bí danh trong truy vấn mẫu.
Robert Rossney

11
Tuyệt đối, Robert - e, d và j sẽ ổn với tôi.
Tony Andrew

8
Tôi sẽ sử dụng emp cho nhân viên, dep cho bộ phận và công việc cho công việc (hoặc có thể là jb) :)
Andrei Rînea

53
var query = "select COUNT(*) from Users where UserName = '" 
            + tbUser.Text 
            + "' and Password = '" 
            + tbPassword.Text +"'";
  1. Người dùng tin tưởng mù quáng
  2. Không sử dụng truy vấn tham số
  3. Mật khẩu Cleartext

Tất cả đều có thể được xử lý một cách hữu ích bằng cách sử dụng lớp trừu tượng cơ sở dữ liệu của một số loại (bất kỳ).
dkretz

@doofledorfer: Đồng ý, tầng trung lưu chắc chắn sẽ tốt hơn trong trường hợp như thế này, cộng với việc cung cấp kết quả bộ nhớ đệm như một hiệu ứng phụ đẹp.
Joe Pineda

Ví dụ tuyệt vời. Nếu một nhà phát triển tìm cách thay thế điều đó bằng một giải pháp tốt, họ sẽ đi được một nửa để trở thành một nhà phát triển SQL đàng hoàng.
Steve McLeod

46

Lỗi của tôi là các bảng Truy cập 450 cột được đặt bởi con trai 8 tuổi của người chăm sóc chó bạn thân của Giám đốc điều hành và bảng tra cứu tinh ranh chỉ tồn tại vì ai đó không biết cách bình thường hóa cơ sở hạ tầng đúng cách.

Thông thường, bảng tra cứu này trông như thế này:

ID INT,
Tên NVARCHAR (132),
IntValue1 INT,
IntValue2 INT,
CharValue1 NVARCHAR (255),
CharValue2 NVARCHAR (255),
NGÀY 1 NGÀY,
Ngày 2 NGÀY

Tôi đã mất số lượng khách hàng tôi đã thấy những người có hệ thống dựa trên sự ghê tởm như thế này.


1
Tệ hơn nữa, tôi đọc được rằng trong phiên bản mới nhất của Access thực sự được hỗ trợ tự động, điều mà tôi sợ sẽ khuyến khích nhiều hơn cho fetichism cột Value1, Value2, Value3 ... này
Joe Pineda

Đợi đã - vậy con trai 8 tuổi là con trai của người chăm sóc chó?
barrypicker

28

Những cái mà tôi không thích nhất là

  1. Sử dụng khoảng trắng khi tạo bảng, sprocs, v.v. Tôi đã gặp phải điều này) thực sự làm tôi khó chịu.

  2. Dữ liệu không chuẩn hóa. Một bảng không cần phải được chuẩn hóa hoàn toàn, nhưng khi tôi gặp một bảng nhân viên có thông tin về điểm đánh giá hiện tại hoặc bất cứ điều gì chính của họ, điều đó cho tôi biết rằng có lẽ tôi sẽ cần phải tạo một bảng riêng biệt vào một lúc nào đó và sau đó cố gắng giữ chúng được đồng bộ hóa. Tôi sẽ bình thường hóa dữ liệu trước và sau đó nếu tôi thấy một nơi giúp chuẩn hóa, tôi sẽ xem xét nó.

  3. Sử dụng quá mức các quan điểm hoặc con trỏ. Lượt xem có một mục đích, nhưng khi mỗi bảng được bao bọc trong một khung nhìn thì nó quá nhiều. Tôi đã phải sử dụng con trỏ một vài lần, nhưng nhìn chung bạn có thể sử dụng các cơ chế khác cho việc này.

  4. Truy cập. Một chương trình có thể là một mô hình chống? Chúng tôi có SQL Server trong công việc của tôi, nhưng một số người sử dụng quyền truy cập do tính khả dụng, "dễ sử dụng" và "thân thiện" với người dùng không có kỹ thuật. Có quá nhiều thứ ở đây để đi vào, nhưng nếu bạn đã ở trong một môi trường tương tự, bạn biết đấy.


2
# 4 - có một chủ đề khác chỉ dành cho <a href=' stackoverflow.com/questions/327199/iêu> :).
dkretz

4
Truy cập KHÔNG phải là DBMS. Đó là một môi trường RAD, bao gồm một trình quản lý cơ sở dữ liệu rất đơn giản. Máy chủ SQL, Oracle, et al. sẽ không bao giờ thay thế nó, trừ khi bạn thêm ngôn ngữ giống VB và cơ sở như Báo cáo Pha lê.
Joe Pineda

26

sử dụng SP làm tiền tố của tên thủ tục lưu trữ vì trước tiên nó sẽ tìm kiếm trong vị trí thủ tục hệ thống thay vì vị trí thủ tục tùy chỉnh.


1
Cũng có thể được mở rộng để sử dụng bất kỳ tiền tố phổ biến nào khác cho tất cả các thủ tục được lưu trữ, khiến việc chọn qua danh sách được sắp xếp trở nên khó khăn hơn.
dkretz

7
+1 cho nhận xét doofledorfer !! Tôi đã thấy điều này rất nhiều, tôi thấy điều này thật ngu ngốc và thực sự làm cho việc tìm kiếm một SP cụ thể rất khó khăn !!! Cũng được mở rộng thành "vw_" cho các lượt xem, "tbl_" cho các bảng và tương tự, tôi ghét chúng như thế nào!
Joe Pineda

1
Các tiền tố có thể hữu ích nếu bạn kịch bản các đối tượng thành tệp (ví dụ: để kiểm soát nguồn, triển khai hoặc di chuyển)
Rick

1
Tại sao trên trái đất nó sẽ hữu ích để tiền tố mỗi thủ tục được lưu trữ với sp hoặc usp? Nó chỉ làm cho việc quét danh sách cho cái bạn muốn trở nên khó khăn hơn.
Ryan Lundy

25

Sử dụng quá mức các bảng tạm thời và con trỏ.


2
Bằng chứng tốt cho thấy "tất cả những gì tôi biết là ngôn ngữ thủ tục".
dkretz

2
Quá lạm dụng bất cứ điều gì là theo định nghĩa không mong muốn. Một ví dụ cụ thể về việc sử dụng bảng tạm thời / con trỏ sẽ không cần thiết sẽ hữu ích.
Jace Rhea

6
Chủ yếu tôi thấy bảng tạm thời được sử dụng. với SQL Server, bạn thường đạt được hiệu suất bằng cách thực hiện công cụ với một loạt các bảng tạm thời thay vì một truy vấn nguyên khối.
Cervo

24

Để lưu trữ giá trị thời gian, chỉ nên sử dụng múi giờ UTC. Giờ địa phương không nên được sử dụng.


3
Tôi vẫn chưa tìm thấy một giải pháp đơn giản tốt để chuyển đổi từ UTC sang giờ địa phương cho các ngày trong quá khứ, khi việc tiết kiệm ánh sáng ban ngày phải được xem xét, với các ngày thay đổi khác nhau theo năm và quốc gia, cũng như tất cả các ngoại lệ trong các quốc gia. Vì vậy, UTC không cứu bạn khỏi sự phức tạp chuyển đổi. Tuy nhiên, điều quan trọng là có một cách để biết múi giờ của mọi thời gian được lưu trữ.
ckarras

1
@CsongorHalmai Nhiều nơi thực hành tiết kiệm ánh sáng ban ngày, vì vậy giá trị thời gian trong vòng một giờ của ca làm việc có thể mơ hồ.
Frank Schwieterman

Điều đó chắc chắn đúng cho hiện tại và quá khứ, nhưng đối với tương lai, đặc biệt là tương lai khá xa, múi giờ rõ ràng thường là một điều cần thiết. Nếu bạn có tùy chọn 30 năm vừa được viết và hết hạn vào năm 2049-09-27T17: 00: 00 giờ New York, thì bạn không thể chỉ mù quáng cho rằng đó sẽ là 21: 00: 00Z. Quốc hội Hoa Kỳ có thể thay đổi các quy tắc DST. Bạn phải tách riêng giờ địa phương và múi giờ thực (America / New_York).
John Cowan

23

sử dụng @@ IDENTITY thay vì SCOPE_IDENTITY ()

Trích dẫn từ câu trả lời này :

  • @@ IDENTITY trả về giá trị nhận dạng cuối cùng được tạo cho bất kỳ bảng nào trong phiên hiện tại, trên tất cả các phạm vi. Bạn cần phải cẩn thận ở đây, vì nó trên phạm vi. Bạn có thể nhận được một giá trị từ một kích hoạt, thay vì tuyên bố hiện tại của bạn.
  • SCOPE_IDENTITY trả về giá trị nhận dạng cuối cùng được tạo cho bất kỳ bảng nào trong phiên hiện tại và phạm vi hiện tại. Nói chung những gì bạn muốn sử dụng.
  • IDENT_CURRENT trả về giá trị nhận dạng cuối cùng được tạo cho một bảng cụ thể trong bất kỳ phiên nào và bất kỳ phạm vi nào. Điều này cho phép bạn chỉ định bảng nào bạn muốn giá trị từ đó, trong trường hợp hai bảng trên không hoàn toàn là thứ bạn cần (rất hiếm). Bạn có thể sử dụng điều này nếu bạn muốn nhận giá trị IDENTITY hiện tại cho một bảng mà bạn chưa chèn bản ghi vào.

+1 rất đúng, có thể gây ra một lỗi khó loại bỏ
Axarydax

23

Sử dụng lại trường 'chết' cho mục đích mà nó không dành cho (ví dụ: lưu trữ dữ liệu người dùng trong trường 'Fax') - rất hấp dẫn như một cách khắc phục nhanh chóng!


21
select some_column, ...
from some_table
group by some_column

và giả sử rằng kết quả sẽ được sắp xếp theo some_column. Tôi đã thấy điều này một chút với Sybase nơi giả định được giữ (hiện tại).


1
upvote cho EVER giả định thứ tự sắp xếp, chỉ vì đó là cách nó xuất hiện trong công cụ truy vấn mà một lần
Joel Coehoorn

3
Tôi thậm chí đã xem báo cáo này là một lỗi nhiều lần.
dkretz

6
trong MySQL, nó được ghi lại để sắp xếp. < dev.mysql.com/doc/refman/5.0/en/select.html >. Vì vậy, đổ lỗi cho MySQL (một lần nữa).
derobert

1
Trong Oracle, các kết quả chưa được sắp xếp (gần như) luôn khớp với nhóm - cho đến phiên bản 10G. Rất nhiều công việc cho các nhà phát triển đã từng bỏ qua ĐẶT HÀNG B! NG!
Tony Andrew

1
Tôi thậm chí đã ở trong một lớp đào tạo nơi điều này được tuyên bố là sự thật cho SQL Server. Tôi đã phải phản đối rất lớn. Để chỉ lưu vào loại 20 ký tự, bạn dựa vào hành vi tối nghĩa hoặc không có giấy tờ.
erikkallen

20
SELECT FirstName + ' ' + LastName as "Full Name", case UserRole when 2 then "Admin" when 1 then "Moderator" else "User" end as "User's Role", case SignedIn when 0 then "Logged in" else "Logged out" end as "User signed in?", Convert(varchar(100), LastSignOn, 101) as "Last Sign On", DateDiff('d', LastSignOn, getDate()) as "Days since last sign on", AddrLine1 + ' ' + AddrLine2 + ' ' + AddrLine3 + ' ' + City + ', ' + State + ' ' + Zip as "Address", 'XXX-XX-' + Substring(Convert(varchar(9), SSN), 6, 4) as "Social Security #" FROM Users

Hoặc, nhồi nhét mọi thứ vào một dòng.


Đã sử dụng truy vấn của một nhận xét trước đó, chỉ vì đó là câu lệnh SQL đầu tiên tôi có sẵn.
Jasper Bekkers

17
  • Các FROM TableA, TableB WHEREcú pháp cho NỐI hơnFROM TableA INNER JOIN TableB ON

  • Giả định rằng một truy vấn sẽ được trả về đã sắp xếp một cách nhất định mà không đặt mệnh đề ORDER BY vào, chỉ vì đó là cách nó xuất hiện trong quá trình thử nghiệm trong công cụ truy vấn.


5
Các DBA Oracle của tôi luôn phàn nàn rằng tôi sử dụng "ANSI tham gia", nghĩa là những gì bạn trình bày là đúng. Nhưng tôi tiếp tục làm điều đó, và tôi nghi ngờ rằng sâu bên dưới họ biết rõ hơn về nó.
Steve McLeod

1
Tôi nghi ngờ rằng Oracle mong muốn SQL tiêu chuẩn sẽ biến mất. :-) Ngoài ra, bạn không thể trộn THAM GIA ngầm và rõ ràng (còn gọi là ANSI THAM GIA) trong MySQL 5 - nó không hoạt động. Đó là một đối số khác cho JION rõ ràng.
staticsan

3
Tôi sẽ nói rằng ngay cả A INNER THAM GIA B ON là một mô hình chống. Tôi thích A INNER THAM GIA B SỬ DỤNG.
John Nilsson

Hiện tại, Oracle đã hỗ trợ cú pháp ANSI, nhưng trước đây họ đã từng sử dụng cú pháp thực sự kỳ lạ này cho các phép nối ngoài và có quá nhiều người vẫn đang sử dụng nó.
Cervo

tốt ... Oracle vẫn sẽ không cho phép bạn sử dụng các phép nối ANSI để xem nhanh được làm mới, theo quan điểm cụ thể hóa theo cam kết
Gerrat

14

Học SQL trong sáu tháng đầu tiên của sự nghiệp và không bao giờ học bất cứ điều gì khác trong 10 năm tiếp theo. Đặc biệt là không học hoặc sử dụng hiệu quả các tính năng SQL phân tích / cửa sổ. Cụ thể là việc sử dụng over () và phân vùng bởi.

Các hàm cửa sổ, giống như các hàm tổng hợp, thực hiện tổng hợp trên một tập hợp xác định (một nhóm) các hàng, nhưng thay vì trả về một giá trị cho mỗi nhóm, các hàm cửa sổ có thể trả về nhiều giá trị cho mỗi nhóm.

Xem O'Reilly SQL Cookbook Phụ lục A để biết tổng quan đẹp về các chức năng cửa sổ.


12

Tôi cần đặt yêu thích hiện tại của riêng tôi ở đây, chỉ để làm cho danh sách đầy đủ. Antipotype yêu thích của tôi không kiểm tra truy vấn của bạn .

Điều này áp dụng khi:

  1. Truy vấn của bạn liên quan đến nhiều hơn một bảng.
  2. Bạn nghĩ rằng bạn có một thiết kế tối ưu cho một truy vấn, nhưng đừng bận tâm kiểm tra các giả định của bạn.
  3. Bạn chấp nhận truy vấn đầu tiên hoạt động, không có manh mối nào về việc nó thậm chí gần với tối ưu hóa hay không.

Và bất kỳ thử nghiệm nào chạy với dữ liệu không điển hình hoặc không đủ đều không được tính. Nếu đó là một thủ tục được lưu trữ, hãy đặt câu lệnh kiểm tra vào một bình luận và lưu nó, với kết quả. Nếu không, đặt nó vào một nhận xét trong mã với kết quả.


Một kỹ thuật rất hữu ích để kiểm tra T-SQL tối thiểu: Trong tệp .Query nơi bạn xác định SP, UDF, v.v., ngay sau khi nó tạo một thử nghiệm khối như IF 1 = 2 BEGIN (trường hợp mẫu cho mã của bạn, với kết quả mong đợi như nhận xét) HẾT
Joe Pineda

SQL Server phân tích mã trong khối kiểm tra, mặc dù nó không bao giờ được thực thi. Vì vậy, khi đối tượng của bạn được sửa đổi và nhận được nhiều tham số hơn, hoặc thuộc loại khác, v.v. hoặc một đối tượng mà nó phụ thuộc vào đã được sửa đổi, bạn sẽ nhận được một lỗi chỉ bằng cách yêu cầu một kế hoạch thực hiện!
Joe Pineda

Không phải lúc nào cũng có thể kiểm tra với dữ liệu thực. Thông thường máy chủ dev / máy chủ "test" được trả lương thấp và nhận được một phần nhỏ của máy chủ trực tiếp. Nói chung các bài kiểm tra được nhăn mặt trên máy chủ trực tiếp. Một số nơi tốt hơn và có một máy chủ thử nghiệm hoặc dàn dựng với dữ liệu trực tiếp.
Cervo

11

Lạm dụng bảng tạm thời.

Cụ thể là loại điều này:

SELECT personid, firstname, lastname, age
INTO #tmpPeople
FROM People
WHERE lastname like 's%'

DELETE FROM #tmpPeople
WHERE firstname = 'John'

DELETE FROM #tmpPeople
WHERE firstname = 'Jon'

DELETE FROM #tmpPeople
WHERE age > 35

UPDATE People
SET firstname = 'Fred'
WHERE personid IN (SELECT personid from #tmpPeople)

Không xây dựng bảng tạm thời từ một truy vấn, chỉ để xóa các hàng bạn không cần.

Và vâng, tôi đã thấy các trang mã ở dạng này trong các DB sản xuất.


1
+1, tôi đồng ý. Mặc dù, tôi đã tìm thấy ít nhất một hoặc hai trường hợp trong đó kỹ thuật này đã cải thiện hiệu suất - các truy vấn liên quan rất phức tạp để nói rằng ít nhất.
a'r

1
Đúng - họ có một vị trí, chỉ là không có trong mọi truy vấn :)
geofftnz

1
Đôi khi bạn phải làm điều đó nếu điều kiện siêu phức tạp. Đúng nó có thể bị lạm dụng đến cực đoan. Nhưng nhiều lần xóa đơn giản đơn giản hơn nhiều so với logic để lấy trường hợp trong truy vấn ban đầu. Ngoài ra, đôi khi nếu mệnh đề không thể mở rộng, truy vấn ban đầu sẽ chậm lại. Nhưng chỉ cần làm nó trên bảng tạm thời nhỏ hơn là hiệu quả hơn. Và những lần khác, bạn tiếp tục thêm các trường hợp mà người kinh doanh tiếp tục thêm sau khi thực tế.
Cervo

9

Quan điểm trái ngược: quá ám ảnh với bình thường hóa.

Hầu hết các hệ thống SQL / RBDB cung cấp một tính năng (giao dịch, sao chép) khá hữu ích, ngay cả với dữ liệu không chuẩn hóa. Dung lượng ổ đĩa rẻ và đôi khi có thể đơn giản hơn (mã dễ dàng hơn, thời gian phát triển nhanh hơn) để thao tác / lọc / tìm kiếm dữ liệu được tìm nạp, hơn là viết lên lược đồ 1NF và xử lý tất cả các rắc rối trong đó (tham gia phức tạp, chọn lọc khó chịu , Vân vân).

Tôi đã tìm thấy các hệ thống quá mức bình thường hóa thường được tối ưu hóa sớm, đặc biệt là trong giai đoạn phát triển ban đầu.

(suy nghĩ nhiều hơn về nó ... http://writeonly.wordpress.com/2008/12/05/simple-object-db-USE-json-and-python-sqlite/ )


22
Tôi nghĩ rằng không bình thường hóa thường là tối ưu hóa sớm.
tuinstoel

Đôi khi, đôi khi không. May mắn thay, thường dễ kiểm tra và các tùy chọn khác nhau hoạt động với các nhu cầu db khác nhau.
Gregg Lind

17
Bình thường hóa không chỉ để tiết kiệm không gian đĩa. Nó cũng là để tạo ra một nguồn có thẩm quyền cho dữ liệu. Nếu dữ liệu chỉ được lưu trữ ở một nơi, thì tính nhất quán không phải là sản phẩm phụ của mã hóa cẩn thận, mà thay vào đó là sản phẩm phụ của thiết kế.
Grant Johnson

Lưu trữ dữ liệu hỗn hợp ở định dạng JSON là một điều: ngày càng có nhiều hỗ trợ hơn cho nó và đó là một sự đánh đổi có ý thức. Sử dụng các giá trị được phân tách bằng dấu phẩy (hoặc bất cứ thứ gì) trong một nỗ lực để lưu một tham gia là khôn ngoan và ngu ngốc.
John Cowan

các giải pháp noQuery đang cho thấy lợi ích về hiệu suất với chi phí dữ liệu trùng lặp bằng cách loại bỏ tra cứu nhiều bảng. Đặt toàn bộ điều bình thường hóa trên đầu của nó. Trong một số ví dụ, dữ liệu được thu thập ở nhiều nơi để đảm bảo một quy trình có thời gian phản hồi nhanh nhất có thể. Tất nhiên, câu hỏi về các nguồn có thẩm quyền đến để chơi.
barrypicker

9

Tôi chỉ kết hợp cái này với nhau, dựa trên một số câu trả lời SQL ở đây trên SO.

Đây là một phản đề nghiêm trọng khi nghĩ rằng các trình kích hoạt là vào cơ sở dữ liệu vì các trình xử lý sự kiện là OOP. Có nhận thức rằng bất kỳ logic cũ nào cũng có thể được đưa vào kích hoạt, sẽ bị loại bỏ khi một giao dịch (sự kiện) xảy ra trên bàn.

Không đúng. Một trong những khác biệt lớn là các kích hoạt là đồng bộ - với sự báo thù, bởi vì chúng đồng bộ trên một hoạt động được thiết lập, không phải trên một hoạt động hàng. Về phía OOP, hoàn toàn ngược lại - các sự kiện là một cách hiệu quả để thực hiện các giao dịch không đồng bộ.


8

Các thủ tục hoặc chức năng được lưu trữ mà không có bất kỳ bình luận nào ...


Và khung nhìn;) Hàm đúng, ngoại trừ các hàm có giá trị bảng (= khung nhìn với tham số).
Stefan Steiger

7

1) Tôi không biết đó là mô hình chống "chính thức", nhưng tôi không thích và cố gắng tránh các chuỗi ký tự như các giá trị ma thuật trong cột cơ sở dữ liệu.

Một ví dụ từ bảng 'hình ảnh' của MediaWiki:

img_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", 
    "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
img_major_mime ENUM("unknown", "application", "audio", "image", "text", 
    "video", "message", "model", "multipart") NOT NULL default "unknown",

(Tôi chỉ nhận thấy vỏ khác nhau, một điều cần tránh)

Tôi thiết kế các trường hợp như tra cứu int vào các bảng ImageMediaType và ImageMajorMime với các khóa chính.

2) chuyển đổi ngày / chuỗi dựa trên cài đặt NLS cụ thể

CONVERT(NVARCHAR, GETDATE())

không có định dạng


Và không có thụt cú pháp, một trong hai. Luận.
dkretz

2
Tại sao điều này là xấu? chắc chắn nếu bạn đang cố gắng thể hiện một tập hợp các giá trị thì nó cũng hoạt động giống như một bảng tra cứu và phù hợp hơn với mã gọi nó. Id thay vào đó là một enum trong mã ứng dụng của tôi ánh xạ tới một ràng buộc enum trong DB của tôi hơn là một enum trong mã ứng dụng của tôi ánh xạ tới các hàng cụ thể của bảng tra cứu. Nó chỉ cảm thấy sạch hơn.
Jack Ryan

@JackRyan: Điều này thật tệ vì khi bạn thay đổi danh sách enum sau này, bạn cần nhớ thay đổi nó ở hai nơi ngay bây giờ. Nó vi phạm KHÔ . Cơ sở dữ liệu nên là nguồn duy nhất của sự thật.
Gerrat

7

Truy vấn con giống hệt nhau trong một truy vấn.


10
Thật không may, đôi khi bạn không thể tránh điều đó - trong SQL 2000 không có từ khóa "VỚI" và sử dụng UDF để đóng gói các truy vấn con phổ biến đôi khi dẫn đến các hình phạt về hiệu suất, đổ lỗi cho MS về điều đó ...
Joe Pineda

Chà, hy vọng họ sẽ đi xung quanh để thêm nó vào một trong những ngày này.
EvilTeach

Trong SQL 2000, bạn có thể sử dụng các biến bảng.
đệ quy

@recursive: bạn không thể có các chỉ mục trên một biến bảng, điều này thường sẽ làm cho nó chậm hơn một truy vấn con. Tuy nhiên, bạn có thể sử dụng một bảng tạm thời với các chỉ mục tùy chỉnh.
Rick

Thật tuyệt, đã làm việc với SQL trong nhiều năm và thậm chí còn không biết Biểu thức bảng chung tồn tại (mặc dù tôi sẽ cần chúng). Bây giờ tôi làm! Cảm ơn!
sleske

7
  • Chế độ xem thay đổi - Chế độ xem bị thay đổi quá thường xuyên và không có thông báo hoặc lý do. Sự thay đổi sẽ được chú ý vào thời điểm không phù hợp nhất hoặc tệ hơn là sai và không bao giờ được chú ý. Có thể ứng dụng của bạn sẽ bị hỏng vì ai đó nghĩ ra một cái tên tốt hơn cho cột đó. Theo quan điểm quy tắc nên mở rộng tính hữu dụng của các bảng cơ sở trong khi duy trì hợp đồng với người tiêu dùng. Khắc phục sự cố nhưng không thêm tính năng hoặc thay đổi hành vi tệ hơn, vì điều đó tạo ra một chế độ xem mới. Để giảm thiểu không chia sẻ quan điểm với các dự án khác và, hãy sử dụng CTE khi nền tảng cho phép. Nếu cửa hàng của bạn có DBA, bạn có thể không thể thay đổi lượt xem nhưng tất cả các lượt xem của bạn sẽ bị lỗi thời và hoặc vô dụng trong trường hợp đó.

  • The Paramed - Một truy vấn có thể có nhiều mục đích không? Có lẽ nhưng người tiếp theo đọc nó sẽ không biết cho đến khi thiền sâu. Ngay cả khi bạn không cần chúng ngay bây giờ, rất có thể bạn sẽ làm được, ngay cả khi nó "chỉ" để gỡ lỗi. Thêm tham số làm giảm thời gian bảo trì và giữ mọi thứ KHÔ. Nếu bạn có một mệnh đề where, bạn nên có các tham số.

  • Trường hợp không có CASE -

    SELECT  
    CASE @problem  
      WHEN 'Need to replace column A with this medium to large collection of strings hanging out in my code.'  
        THEN 'Create a table for lookup and add to your from clause.'  
      WHEN 'Scrubbing values in the result set based on some business rules.'  
        THEN 'Fix the data in the database'  
      WHEN 'Formating dates or numbers.'   
        THEN 'Apply formating in the presentation layer.'  
      WHEN 'Createing a cross tab'  
        THEN 'Good, but in reporting you should probably be using cross tab, matrix or pivot templates'   
    ELSE 'You probably found another case for no CASE but now I have to edit my code instead of enriching the data...' END  

Yêu người thứ ba đó. Tôi đã sử dụng nó cục bộ ...
alphadogg

Cảm ơn các đạo cụ. :)
jason saldo

5

Hai thứ tôi tìm thấy nhiều nhất và có thể có một chi phí đáng kể về mặt hiệu suất là:

  • Sử dụng con trỏ thay vì một biểu thức dựa trên tập hợp. Tôi đoán điều này xảy ra thường xuyên khi lập trình viên đang suy nghĩ thủ tục.

  • Sử dụng các truy vấn phụ tương quan, khi tham gia vào bảng dẫn xuất có thể thực hiện công việc.


Tôi đồng ý nếu bạn có nghĩa là những gì tôi nghĩ bạn có nghĩa là; mặc dù truy vấn phụ tương quan là một loại bảng IIRC dẫn xuất.
dkretz

1
Bảng dẫn xuất là một hoạt động được thiết lập, trong khi truy vấn con tương quan chạy cho từng hàng trong truy vấn bên ngoài, làm cho nó kém hiệu quả hơn (9 lần trong số 10)
Mitch Wheat

Một vài năm trước tôi đã ngạc nhiên rằng SQL S. bằng cách nào đó được tối ưu hóa để xử lý các truy vấn tương quan: đối với những truy vấn đơn giản, bạn có cùng một kế hoạch thực hiện như với một truy vấn tương đương logic bằng cách sử dụng THAM GIA! Ngoài ra, các truy vấn tương quan khiến Oracle phải quỳ xuống chỉ chạy chậm trên SQL S.!
Joe Pineda

Đó là lý do tại sao tôi luôn kiểm tra cả hai cách. Và tôi <i> do </> thường thử cả hai cách. Trong thực tế, đối với SQL Server, tôi thường thấy sq tương quan không chậm hơn.
dkretz

3
Xin vui lòng hiểu rằng một truy vấn con tương quan và tham gia là SẮC (trong hầu hết các trường hợp). Chúng thậm chí không phải là những thứ khác nhau được tối ưu hóa cho nhau, mà chỉ là những cách trình bày văn bản khác nhau của cùng một hoạt động.
erikkallen

5

Đưa công cụ vào các bảng tạm thời, đặc biệt là những người chuyển từ SQL Server sang Oracle có thói quen lạm dụng các bảng tạm thời. Chỉ cần sử dụng các câu lệnh chọn lồng nhau.


5

Các nhà phát triển viết các truy vấn mà không có ý tưởng tốt về những gì làm cho các ứng dụng SQL (cả truy vấn riêng lẻ và hệ thống nhiều người dùng) nhanh hay chậm. Điều này bao gồm sự thiếu hiểu biết về:

  • Các chiến lược tối thiểu hóa I / O vật lý, cho rằng nút thắt của hầu hết các truy vấn là I / O không phải CPU
  • tác động hoàn hảo của các loại truy cập lưu trữ vật lý khác nhau (ví dụ: nhiều I / O tuần tự sẽ nhanh hơn rất nhiều I / O ngẫu nhiên nhỏ, mặc dù ít hơn nếu bộ lưu trữ vật lý của bạn là SSD!)
  • làm cách nào để điều chỉnh truy vấn nếu DBMS tạo ra một kế hoạch truy vấn kém
  • cách chẩn đoán hiệu suất cơ sở dữ liệu kém, cách "gỡ lỗi" truy vấn chậm và cách đọc kế hoạch truy vấn (hoặc GIẢI THÍCH, tùy thuộc vào DBMS bạn chọn)
  • khóa chiến lược để tối ưu hóa thông lượng và tránh bế tắc trong các ứng dụng đa người dùng
  • tầm quan trọng của việc trộn và các thủ thuật khác để xử lý việc xử lý các tập dữ liệu
  • thiết kế bảng và chỉ mục để cân bằng tốt nhất không gian và hiệu suất (ví dụ: bao gồm các chỉ mục, giữ các chỉ mục nhỏ nếu có thể, giảm các loại dữ liệu xuống kích thước tối thiểu cần thiết, v.v.)

3

Sử dụng SQL như một gói ISAM (Phương pháp truy cập tuần tự được lập chỉ mục) được tôn vinh. Cụ thể, các con trỏ lồng nhau thay vì kết hợp các câu lệnh SQL thành một câu lệnh, mặc dù lớn hơn ,. Điều này cũng được tính là "lạm dụng trình tối ưu hóa" vì thực tế không có nhiều trình tối ưu hóa có thể làm. Điều này có thể được kết hợp với các tuyên bố không được chuẩn bị để không hiệu quả tối đa:

DECLARE c1 CURSOR FOR SELECT Col1, Col2, Col3 FROM Table1

FOREACH c1 INTO a.col1, a.col2, a.col3
    DECLARE c2 CURSOR FOR
        SELECT Item1, Item2, Item3
            FROM Table2
            WHERE Table2.Item1 = a.col2
    FOREACH c2 INTO b.item1, b.item2, b.item3
        ...process data from records a and b...
    END FOREACH
END FOREACH

Giải pháp đúng (hầu như luôn luôn) là kết hợp hai câu lệnh CHỌN thành một:

DECLARE c1 CURSOR FOR
    SELECT Col1, Col2, Col3, Item1, Item2, Item3
        FROM Table1, Table2
        WHERE Table2.Item1 = Table1.Col2
        -- ORDER BY Table1.Col1, Table2.Item1

FOREACH c1 INTO a.col1, a.col2, a.col3, b.item1, b.item2, b.item3
    ...process data from records a and b...
END FOREACH

Ưu điểm duy nhất cho phiên bản vòng lặp kép là bạn có thể dễ dàng phát hiện các ngắt giữa các giá trị trong Bảng 1 vì vòng lặp bên trong kết thúc. Đây có thể là một yếu tố trong các báo cáo phá vỡ kiểm soát.

Ngoài ra, sắp xếp trong ứng dụng thường là không.


Phong cách, mặc dù không phải là cú pháp này, đặc biệt tràn lan trong PHP theo kinh nghiệm của tôi.
dkretz

Cú pháp thực sự là IBM Informix-4GL - nhưng rõ ràng là không cần nhiều cách giải thích (tôi nghĩ). Và phong cách tràn lan trong rất nhiều chương trình SQL - bất kể ngôn ngữ lập trình.
Jonathan Leffler

Ngoại trừ thực tế là bạn đang sử dụng một antipotype nổi tiếng (tham gia ngầm) để minh họa cho antipotype của bạn, loại đánh bại điểm.
Johan

Và tất nhiên, việc sử dụng các con trỏ hoàn toàn là một antipotype. Hầu như tất cả các con trỏ có thể được viết lại dưới dạng các hoạt động dựa trên tập hợp. Một số ít không thể là loại mà chỉ các DBA có nhiều năm kinh nghiệm và là người hiểu cách thức hoạt động của các cơ sở dữ liệu. Không có nhà phát triển ứng dụng nào cần phải viết một con trỏ SQL.
HLGEM

3

Sử dụng khóa chính làm đại diện thay thế cho địa chỉ hồ sơ và sử dụng khóa ngoại làm thay thế cho con trỏ được nhúng trong hồ sơ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.