2010-09-10 46 views
8

Chúng tôi đang phát triển việc làm ETL và tư vấn của chúng tôi đã được sử dụng "kiểu cũ" SQL khi tham gia bảngSQL tham gia: Tương lai của tiêu chuẩn ANSI SQL (nơi vs tham gia)?

select a.attr1, b.attr1 
from table1 a, table2 b 
where a.attr2 = b.attr2 

thay vì sử dụng liên kết nội khoản

select a.attr1, b.attr1 
from table1 as a inner join table2 as b 
    on a.attr2 = b.attr2 

Câu hỏi của tôi là trong thời gian dài , có rủi ro khi sử dụng "nơi tham gia" cũ không? Bao lâu loại tham gia này được hỗ trợ và giữ như là tiêu chuẩn ANSI? Nền tảng của chúng tôi là SQL Server và nguyên nhân chính của tôi là trong tương lai, "nơi tham gia" không còn được hỗ trợ. Khi điều này xảy ra, chúng ta phải sửa đổi tất cả các công việc ETL của chúng tôi bằng cách sử dụng kiểu "join join" của các join.

Trả lời

7

Tôi nghi ngờ rằng "nơi tham gia" sẽ không được hỗ trợ. Nó chỉ là không thể không hỗ trợ chúng, bởi vì chúng được dựa trên các sản phẩm Descartes và lọc đơn giản. Họ thực sự không tham gia.

Nhưng có nhiều lý do để sử dụng cú pháp nối mới hơn.Trong số những người khác:

  • Độ khó
  • Bảo trì
  • Dễ dàng thay đổi bên ngoài tham gia
4

Có nhiều lý do để tránh tham gia ngầm định. Những cái lớn là:

  • Không thể thay đổi dễ dàng thành kết nối bên ngoài.
  • Dễ dàng quên điều kiện tham gia hơn với sự tham gia ngầm định.
  • Nếu bạn kết hợp cả hai tham gia ngầm định và rõ ràng, bạn gặp vấn đề với ưu tiên khó hiểu. Dưới đây là ví dụ từ một vài giờ trước: MySQL Syntax error

Tôi không nghĩ rằng chúng sẽ sớm bị xóa, nhưng có nhiều lý do khác để ngừng sử dụng chúng.

2

Miễn là chúng không sử dụng *** = và = * cho cú pháp nối của chúng (đã là deprecated as of SQL Server 2008 R2), tôi không thể thấy nó biến mất trong thời gian dài, nhưng như Mark Byers nói, có rất nhiều lý do để không làm điều đó.

Mối quan tâm lớn nhất của tôi là nếu họ đang viết các gia nhập như thế này, thì những gì khác họ có thực hiện điều đó độc đáo không?

8

Thay vì lo lắng về một số rủi ro có thể xảy ra trong tương lai, tại sao bạn không lo lắng về rủi ro mà bạn phải đối mặt ngay bây giờ?

Ngoài điểm của Mark:

  • Mã này là khó khăn hơn để đọc (và do đó hiểu mục đích của) khi ON khoản được ngắt kết nối (đôi khi nhiều dòng) từ các bảng tham gia. Điều này làm tăng khả năng xảy ra lỗi khi sửa đổi mã.
  • Xác định loại JOIN nào đang được thực hiện khó hơn - bạn phải lướt qua mệnh đề WHERE và hy vọng rằng những gì bạn thấy là đúng.
  • Tìm thiếu mệnh đề JOIN khó hơn nhiều, tăng nguy cơ tham gia vô ý của Descartes - khi bạn sử dụng cú pháp ANSI, mệnh đề ON xếp hàng độc đáo, làm cho việc này trở nên tầm thường.
3

Cả hai cú pháp được hỗ trợ bởi các phiên bản mới nhất của ISO SQL (2003,2008). Sử dụng dấu phẩy để chỉ định một phép nối chéo trong mệnh đề FROM là SQL chuẩn hoàn toàn và được hỗ trợ bởi tất cả các produts SQL mà tôi đã gặp. Có vẻ như rất có khả năng nó sẽ không bao giờ hoặc thậm chí có thể bị phản đối hoặc không được hỗ trợ trong SQL.

-2

Nếu bạn lo lắng chúng sẽ bị xóa khỏi Standard hoặc từ các sản phẩm SQL thì đừng lo lắng. Nó không có khả năng xảy ra bao giờ hết.

'Phong cách cũ' này tham gia chỉ là: chỉ là một câu hỏi về phong cách. Những người ủng hộ nó thề có những tình huống mà sự tham gia 'kiểu cũ' dễ hiểu hơn. Trong khi tôi không hoàn toàn thuyết phục bản thân mình, một điều chắc chắn: phong cách cũ tham gia sẽ gặp phải theo thời gian và mã kỹ thuật lại cho phù hợp với phong cách cá nhân của riêng bạn không phải lúc nào cũng phù hợp. Do đó, làm quen với phong cách và học cách làm việc với nó.

+0

Không có chúng không chỉ là vấn đề về phong cách, có những vấn đề rất thực tế khi sử dụng kiểu tham gia này. – HLGEM

+0

@ HLGEM - bạn chỉ nói rằng bởi vì nó không phù hợp với khẩu vị của bạn. – onedaywhen

+0

Np Tôi nói rằng vì nó gây ra các kết quả truy vấn sai và các vấn đề về bảo trì. – HLGEM

0

Cú pháp ngụ ý bên phải và bên trái * = và = * không được chấp nhận và vì lý do chính đáng, hiện tại, không trả về kết quả chính xác vào mọi lúc. Nếu họ đã sử dụng này, những PHẢI được cố định ngay bây giờ vì họ hiện đang đưa bạn vào nguy cơ cho kết quả không chính xác. Đây không phải là một lựa chọn. Cú pháp khác sẽ tiếp tục hoạt động nhưng cũng nên được thay thế vì nhiều lý do. Đầu tiên là rất dễ dàng để có được tham gia chéo tình cờ mà có thể trả về kết quả xấu hoặc được cố định bằng cách sử dụng riêng biệt mà có thể tạo ra các vấn đề hiệu suất.

Một vấn đề khác là bảo trì. Nếu mọi người sau đó thêm các phép nối khác vào truy vấn và bắt đầu trộn các tham gia ngụ ý và rõ ràng một lần nữa, bạn có thể nhận được kết quả sai và thậm chí không biết nó. Nó là RẤT RẤT xấu để lại loại mã crappy trong codebase của bạn. Các tham gia ngụ ý cũng khó hiểu hơn và vì chúng thường được viết bởi các nhà phát triển không hiểu các tham gia, chúng có thể không phải là những gì bạn cần. Và nếu có một tham gia chéo trong truy vấn như thế nào là người duy trì để biết nếu nó là một lỗi (và tham gia chéo ngẫu nhiên) hoặc một tham gia chéo có chủ ý (chúng tôi đôi khi thực sự cần chúng). Tôi sẽ không chấp nhận mã này như được viết. Tôi sẽ nhấn mạnh rằng người không đủ năng lực đã viết nó, sửa chữa nó mà không phải trả thêm phí.

1

Rất khó để tranh luận về sự sang trọng hoặc sự xấu xí của một cấu trúc cú pháp nhất định. Bạn chỉ nhìn thấy nó hay không. Cú pháp nối phân cách bằng dấu phẩy phản ánh tính năng cơ bản của Đại số Quan hệ, xác nhận dạng bình thường cho các truy vấn chọn-dự án-tham gia. Loại tham gia duy nhất thoát khỏi nó (và do đó, đảm bảo một cú pháp chuyên dụng) là kết nối bên ngoài. Sai lầm ngẫu nhiên của các biến vị ngữ mất tích mà làm cho việc phân tách đồ thị kết nối chỉ là vấn đề phức tạp của công cụ lập trình SQL mặt trước của bạn là như thế nào (nó có hiển thị tham gia đồ thị không?).

Nó không chỉ mang tính thẩm mỹ. Cơ sở dữ liệu sản xuất thường có các cột như CREATED_ON hoặc COMMENTS trên nhiều bảng. Trong trường hợp này cú pháp NATURAL JOIN rất đơn giản.

Vì Anthony Molinaro (tác giả của sách "SQL Cookbook" nổi tiếng) đã đặt nó một cách hùng hồn: “Kiểu cũ ngắn và ngọt ngào và hoàn hảo. ANSI câm nó xuống, và đối với những người đã phát triển đôi khi, nó hoàn toàn không cần thiết ".

+1

Tôi thực sự không thấy các điều kiện tương tự như thế nào, chỉ đơn giản là nằm ở một nơi khác, là "ngừng hoạt động". Và với các phần mở rộng mới của SQL Server của CROSS APPLY và OUTER APPLY, thậm chí còn có nhiều thứ không thể thực hiện được với các kết nối kiểu cũ. Tôi sợ nói rằng lập luận ở đây nghe có vẻ giống như một con khủng long đang nắm giữ câu lạc bộ đá của anh ấy (mặc dù có nhiều sức mạnh hơn nếu bạn thích nó). Chỉ cần không gọi nó là câm khi nó không! Ngoài ra, tôi không thấy các cột chung cho nhiều bảng là bất kỳ mối nguy hiểm mới nào. Nếu bạn không sử dụng bí danh, bạn đang gặp rắc rối theo cách nào đó. – ErikE

1

dân đã có một số điểm tốt nhưng cho đến nay có hai công trình lớn chưa được đề cập:

  1. Cho dù kiểu cũ hay không * = và = * bên ngoài tham gia đã đưa ra kết quả chính xác, họ cũng không thể biểu thị chính xác một số kết nối nhất định. Hãy xem xét truy vấn sau đây. Chúng tôi muốn hiển thị tất cả khách hàng chưa đặt hàng trên $ 100:

    SELECT 
    FROM 
        Customer C 
        LEFT JOIN Order O ON C.OrderID = O.OrderID AND O.OrderTotal >= 100.0; 
    WHERE 
        O.OrderID IS NULL; 
    

    Hãy thử và thể hiện cách cũ ... nếu có thể. Không sử dụng các bảng có nguồn gốc.

  2. Đối với tôi những giá trị to lớn của việc sử dụng thích hợp tham gia điều khoản là sự tách biệt theo tiêu chuẩn điều kiện tham gia (trong đó sẽ được áp dụng trong hầu hết các truy vấn liên quan đến những hai bảng) từ các bộ lọc đặc biệt cho truy vấn này sẽ trả lại mong muốn hàng:

    SELECT 
        C.FullName, 
        C.CustomerCode, 
        O.OrderDate, 
        O.OrderTotal, 
        OD.ExtendedShippingNotes 
    FROM 
        Customer C 
        INNER JOIN Order O ON C.CustomerID = O.CustomerID 
        INNER JOIN OrderDetail OD ON O.OrderID = OD.OrderID 
    WHERE 
        C.CustomerStatus = 'Preferred' 
        AND O.OrderTotal > 1000.0; 
    

    Sự tách biệt này có nghĩa là nhà phát triển xem xét truy vấn không phải đối phó với một loạt lộn xộn trong khi quét tìm những khác biệt của truy vấn này. Nếu anh ta quen thuộc với các bảng, anh ta có thể bỏ qua mệnh đề FROM hoàn toàn và chỉ cần đọc mệnh đề WHERE để lấy tất cả thông tin mà anh ta cần. Đó là nhanh hơn. Và nếu bạn không quan tâm nhanh hơn, ngay cả khi chỉ quét các truy vấn bằng nhãn cầu của bạn, tôi không muốn làm việc với bạn.

    Bây giờ với những người nghĩ có điều gì đó đặc biệt về vị trí của mọi thứ khi sử dụng cú pháp JOIN, bạn đã sai. Truy vấn sau hoạt động tốt như trên:

    SELECT 
        C.FullName, 
        C.CustomerCode, 
        O.OrderDate, 
        O.OrderTotal, 
        OD.ExtendedShippingNotes 
    FROM 
        Customer C 
        CROSS JOIN Order O 
        INNER JOIN OrderDetail OD 
         ON C.CustomerID = O.CustomerID 
         AND C.CustomerStatus = 'Preferred' 
         AND O.OrderTotal > 1000.0 
    WHERE 
        O.OrderID = OD.OrderID; 
    

    Truy vấn này thậm chí có thể có cùng một kế hoạch thực hiện chính xác. Ngạc nhiên? Đừng thế. Cũng giống như cú pháp kiểu cũ, trình tối ưu hóa là một trong những người chịu trách nhiệm tìm ra cách tham gia các bảng của bạn dựa trên các điều kiện bạn cung cấp. Nó không thực sự quan trọng, nơi các điều kiện được miễn là họ không đề cập đến một bảng chưa được đề cập đến.

Vậy sự khác biệt lớn giữa hai kiểu là gì? Nếu bạn nghĩ rằng truy vấn hỗn hợp thứ hai ở trên là khó hiểu và sẽ là một cách điên rồ để viết, sau đó, tốt, bạn tự nhiên nghĩ rằng phong cách cũ của truy vấn là lame. Bởi vì, thẳng thắn, đặt tất cả các điều kiện một cách bất ngờ vào bất kỳ nơi cũ nào là vô tổ chức. Hệ thống tổ chức của JOIN có ý nghĩa. Nếu bạn quen với phong cách cũ và không thực sự thích phong cách mới, đó có thể là do sự thay đổi khó chịu (đối với tất cả chúng ta). Nhưng một khi bạn sử dụng nó một thời gian, tôi chắc chắn nó sẽ phát triển trên bạn. Ít nhất, nếu không, tôi không thể hiểu tại sao.

+0

Tôi sẽ biến đối số của bạn trên đầu của nó. Vì vậy, ANSI cung cấp cho bạn một cách để cấu trúc truy vấn của bạn tốt hơn nhưng không có cách nào thực thi nó? Tôi muốn đặt cược một số nhà phát triển sẽ tận dụng lợi thế của việc tạo ra mess của nó (trên thực tế, đây là lý do tại sao tôi ở đây). Đối với các kết nối bên ngoài, không có đối số ở đó - tham gia này không phải là kết hợp, bạn phải đặt dấu ngoặc đơn để phân biệt lồng nhau, ít nhất. ANSI nên có chỉ sửa chữa các tham gia bên ngoài và để lại các sản phẩm phái sinh tham gia sản phẩm duy nhất. –

+0

@Tegiri Tôi rất tiếc phải nói rằng tôi không thực sự hiểu những gì bạn đang nói đến. Cả kiểu cũ lẫn kiểu ANSI đều không tham gia vào bất kỳ thứ gì. Vì vậy, không có vấn đề ở đó. Và bạn vẫn có thể sử dụng dấu ngoặc đơn nếu bạn muốn. Hoặc, bạn chỉ có thể di chuyển các mệnh đề ON xung quanh để mô phỏng dấu ngoặc đơn và thực thi thứ tự tham gia (và không có sự mơ hồ). Ngoài ra, bạn có thể nhận được các sản phẩm Descartes tất cả các bạn thích với 'CROSS JOIN' hoặc thậm chí' INNER JOIN ON 1 = 1'. Làm thế nào bạn có kinh nghiệm với ANSI tham gia? – ErikE