Ảnh hưởng của các phép nối trong một tập bản ghi
Trong bài viết thứ sáu và cũng là bài cuối cùng của loạt bài theo dõi ODBC, chúng ta sẽ xem xét cách Access sẽ xử lý các phép nối trong truy vấn Access. Trong bài viết trước, bạn đã biết cách Access xử lý các bộ lọc. Tùy thuộc vào biểu thức, Access có thể chọn tham số hóa nó hoặc có thể buộc phải tự đánh giá nó bằng cách tải xuống tất cả dữ liệu đầu vào, sau đó thực hiện các đánh giá cục bộ. Trong bài viết này, chúng tôi sẽ tập trung vào các phép nối. Khi bạn nghĩ về nó, các phép nối thực sự là một loại bộ lọc đặc biệt. Do đó, về lý thuyết, Access phải điều khiển từ xa càng nhiều càng tốt ngay cả với các phép nối. Bạn thường có thể thấy các phép nối được viết bằng SQL giả sau:
FROM a INNER JOIN b ON a.ID = b.IDTuy nhiên, nó có thể được coi là tương đương với cú pháp sau:
FROM a, b WHERE a.ID = b.IDĐiều đó minh họa rằng mặc dù chúng ta có thể sử dụng
JOIN..ON
dễ đọc và quen thuộc hơn , Quyền truy cập miễn phí để coi nó như một WHERE
điều này rất hữu ích trong các tình huống Access không thể điều khiển từ xa hoàn toàn truy vấn. Nhưng đây là sự thật… khi nào Access quyết định điều khiển từ xa các liên kết? Hãy thử một truy vấn tham gia đơn giản: SELECT c.CityID ,c.StateProvinceID ,c.CityName ,s.StateProvinceName FROM Cities AS c INNER JOIN StateProvinces AS s ON c.StateProvinceID = s.StateProvinceID;Nếu chúng ta theo dõi truy vấn đó, chúng ta sẽ thấy kết quả sau:
SQLExecDirect: SELECT "c"."CityID" ,"s"."StateProvinceID" FROM "Application"."Cities" "c", "Application"."StateProvinces" "s" WHERE ("c"."StateProvinceID" = "s"."StateProvinceID" ) SQLPrepare: SELECT "CityID" ,"CityName" ,"StateProvinceID" FROM "Application"."Cities" WHERE "CityID" = ? SQLExecute: (GOTO BOOKMARK) SQLPrepare: SELECT "StateProvinceID" ,"StateProvinceName" FROM "Application"."StateProvinces" WHERE "StateProvinceID" = ? SQLExecute: (GOTO BOOKMARK) SQLPrepare: SELECT "StateProvinceID" ,"StateProvinceName" FROM "Application"."StateProvinces" WHERE "StateProvinceID" = ? OR "StateProvinceID" = ? OR "StateProvinceID" = ? OR "StateProvinceID" = ? OR "StateProvinceID" = ? OR "StateProvinceID" = ? OR "StateProvinceID" = ? OR "StateProvinceID" = ? OR "StateProvinceID" = ? OR "StateProvinceID" = ? SQLExecute: (MULTI-ROW FETCH) SQLPrepare: SELECT "CityID" ,"CityName" ,"StateProvinceID" FROM "Application"."Cities" WHERE "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH)Access đã quyết định không kết hợp từ xa, mặc dù truy vấn Access ban đầu hoàn toàn có khả năng được thực thi tại SQL Server. Thay vào đó, nó lấy ID từ mỗi bảng trong một tham gia theta, sau đó thiết lập 2 chuỗi truy vấn riêng biệt như thể chúng ta đã mở 2 tập bản ghi kiểu dynaset. Hai truy vấn đã chuẩn bị khác nhau sau đó sẽ được cấp khóa cho các bảng tương ứng từ truy vấn đầu tiên. Có thể đoán trước được, có thể sẽ rất nhiều chuyện khi sử dụng mạng.
Nếu chúng tôi thay đổi cùng một truy vấn Access thành một loại ảnh chụp nhanh thay vì loại dynaset mặc định, chúng tôi nhận được:
SQLExecDirect: SELECT "c"."CityID" ,"c"."CityName" ,"c"."StateProvinceID" ,"s"."StateProvinceName" FROM "Application"."Cities" "c", "Application"."StateProvinces" "s" WHERE ("c"."StateProvinceID" = "s"."StateProvinceID" )Vì vậy, Access thực hiện điều khiển từ xa các phép nối chỉ tốt trong trường hợp truy vấn kiểu ảnh chụp nhanh. Tại sao Access không thực hiện điều đó với truy vấn kiểu dynaset ban đầu? Manh mối nằm trong ảnh chụp màn hình sau đây, nơi chúng tôi cố gắng chỉnh sửa cả hai cột của bảng trong ảnh chụp màn hình sau:
Truy vấn như vậy cho phép cập nhật lên cả hai cột. Điều đó không thực sự diễn đạt được trong SQL nhưng hành động đó là hợp pháp để người dùng thực hiện. Do đó, để thực thi bản cập nhật đó, Access sẽ gửi ODBC SQL sau:
SQLExecDirect: UPDATE "Application"."StateProvinces" SET "StateProvinceName"=? WHERE "StateProvinceID" = ? AND "StateProvinceName" = ? SQLExecDirect: UPDATE "Application"."Cities" SET "CityName"=? WHERE "CityID" = ? AND "CityName" = ? AND "StateProvinceID" = ?Điều đó sẽ không thể thực hiện được nếu Access không có thông tin cần thiết để cập nhật từng bảng, điều này giải thích tại sao Access chọn không kết nối từ xa khi giải quyết truy vấn kiểu dynaset ban đầu. Bài học ở đây là nếu bạn không cần truy vấn có thể cập nhật được và dữ liệu kết quả đủ nhỏ, có thể tốt hơn là chuyển đổi truy vấn thành một loại ảnh chụp nhanh. Trong trường hợp bạn cần tạo một nguồn bản ghi phức tạp, bạn thường sẽ nhận được hiệu suất tốt hơn nhiều khi sử dụng dạng xem SQL làm cơ sở hơn là thực hiện các phép nối ở phía Access.
Để chứng minh điều này, chúng tôi sẽ tạo một dạng xem SQL và liên kết nó với Access:
CREATE VIEW dbo.vwCitiesAndStates AS SELECT c.CityID ,c.StateProvinceID ,c.CityName ,s.StateProvinceName FROM Application.Cities AS c INNER JOIN Application.StateProvinces AS s ON c.StateProvinceID = s.StateProvinceID;Sau đó, chúng tôi điều chỉnh truy vấn Access như sau:
SELECT c.CityID ,c.StateProvinceID ,c.CityName ,c.StateProvinceName FROM vwCitiesAndStates AS c;Nếu sau đó chúng tôi lặp lại bản cập nhật mà chúng tôi đã thử ban đầu, chúng tôi sẽ thấy ODBC SQL được theo dõi sau:
SQLExecDirect: SELECT "c"."CityID" FROM "dbo"."vwCitiesAndStates" "c" SQLPrepare: SELECT "CityID" ,"StateProvinceID" ,"CityName" ,"StateProvinceName" FROM "dbo"."vwCitiesAndStates" WHERE "CityID" = ? SQLExecute: (GOTO BOOKMARK) SQLPrepare: SELECT "CityID" ,"StateProvinceID" ,"CityName" ,"StateProvinceName" FROM "dbo"."vwCitiesAndStates" WHERE "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? OR "CityID" = ? SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH) SQLExecute: (GOTO BOOKMARK) SQLExecDirect: UPDATE "dbo"."vwCitiesAndStates" SET "CityName"=?, "StateProvinceName"=? WHERE "CityID" = ? AND "StateProvinceID" = ? AND "CityName" = ? AND "StateProvinceName" = ?Điều này chứng tỏ rằng việc sử dụng các dạng xem SQL để “điều khiển từ xa” các phép nối, Access sẽ chỉ hoạt động với một nguồn duy nhất, thay vì với 2 bảng và từ xa bản cập nhật trên dạng xem hoàn toàn tới SQL Server. Một tác dụng phụ là bản cập nhật này bây giờ sẽ không thành công với thông báo lỗi:
Điều đó không có gì ngạc nhiên vì chúng tôi đã thực hiện UPDATE
trên một nguồn duy nhất trong khi trong ví dụ ban đầu, Access thực sự đã bí mật phát hành hai riêng UPDATE
các câu lệnh trên mỗi bảng riêng lẻ. Hy vọng rằng điều đó sẽ giúp giải quyết trường hợp bạn nên tránh thực hiện các phép nối trong truy vấn Access / bản ghi / nguồn hàng, đặc biệt khi chúng cần được cập nhật. Nếu không, hãy sử dụng ảnh chụp nhanh nếu có thể.
Ghi chú nhanh về các phép nối không đồng nhất
Chúng tôi cần nhận xét về các phép nối giữa hai bảng được liên kết đến từ hai nguồn dữ liệu ODBC khác nhau. Các phép nối như vậy là "không đồng nhất" vì Access phải xử lý các phép nối cục bộ vì mỗi nguồn dữ liệu được giả định là không biết nhau. Bất kể bạn chỉ định tập bản ghi kiểu dynaset hay kiểu ảnh chụp nhanh, Access phải tìm nạp bộ khóa đầy đủ từ mỗi nguồn dữ liệu và giải quyết các phép nối bằng cách gửi các truy vấn được tham số hóa riêng biệt tới từng nguồn dữ liệu. Nếu cho phép cập nhật, Access sẽ tạo một UPDATE
riêng biệt truy vấn đến từng nguồn dữ liệu cần được cập nhật. Cũng cần lưu ý rằng một phép nối giữa hai bảng được liên kết đến từ hai cơ sở dữ liệu khác nhau, mỗi bảng vẫn được Access coi là không đồng nhất. Điều đó vẫn đúng ngay cả khi hai cơ sở dữ liệu nằm trên cùng một máy chủ và bạn không gặp vấn đề gì khi thực hiện các truy vấn cơ sở dữ liệu chéo. Trong trường hợp này, chế độ xem SQL có thể giúp giảm bớt những lời tán gẫu bổ sung bằng cách ẩn các kết hợp cơ sở dữ liệu chéo khỏi Access tương tự như những gì chúng ta đã thấy trong bài viết này.
Sự khác biệt về cú pháp kết hợp bên ngoài
Miễn là các phép nối bên ngoài không ảnh hưởng đến khả năng cập nhật của truy vấn Access, Access sẽ xử lý nó tương tự như cách nó xử lý phiên bản nối bên trong. Nếu chúng tôi sửa đổi cùng một truy vấn mà chúng tôi từng là một phép nối bên trái, ODBC SQL được theo dõi sẽ xuất ra truy vấn tổng hợp khóa như sau:
SQLExecDirect: SELECT "c"."CityID" ,"s"."StateProvinceID" FROM {oj "Application"."Cities" "c" LEFT OUTER JOIN "Application"."StateProvinces" "s" ON ("c"."StateProvinceID" = "s"."StateProvinceID" ) }Cú pháp trông khá khác so với những gì bạn có thể mong đợi trong các phương ngữ SQL khác. Đó là vì ngữ pháp SQL ODBC yêu cầu bất kỳ liên kết bên ngoài nào phải được bao bọc trong một
{oj ...}
biểu hiện. Để biết thêm chi tiết về cú pháp đó, hãy tham khảo tài liệu. Vì mục đích của chúng tôi, chúng tôi có thể bỏ qua {oj
và đóng }
như tiếng ồn. Kết luận
Chúng tôi thấy rằng các liên kết được coi như thể chúng là một loại bộ lọc và Access sẽ cố gắng điều khiển các liên kết từ xa đến những nơi nó được phép. Một lĩnh vực cụ thể cần chú ý là thực tế là theo mặc định, chúng ta sử dụng tập bản ghi loại dynaset và Access sẽ không đưa ra giả định về việc chúng ta có muốn cho phép sửa đổi các cột như vậy trong tập bản ghi hay không và loại bỏ nó để làm cho chúng ta có thể. để cập nhật lên hai bảng mà trên thực tế không dễ thể hiện trong SQL tiêu chuẩn. Do đó, Access sẽ thực hiện nhiều công việc hơn nữa để hỗ trợ khả năng cập nhật cho truy vấn có chứa các phép nối có thể tác động tiêu cực đến hiệu suất.
Chúng tôi có thể giúp tránh bị phạt bằng cách sử dụng các dạng xem SQL thay cho các phép nối được thể hiện trong một truy vấn Access. Sự cân bằng là sau đó chúng ta phải tuân theo các quy tắc về khả năng cập nhật của dạng xem SQL; chúng tôi có thể không được phép cập nhật hai bảng cùng một lúc. Thông thường vì biểu mẫu Access được thiết kế tốt sẽ chỉ đại diện cho một bảng duy nhất để cập nhật, điều đó không có nhiều hạn chế và là một kỷ luật tốt để tuân theo.
Với điều đó, loạt phim hiện tại đã được thực hiện. Tuy nhiên, việc học mà loạt bài hy vọng có tia lửa điện không nên được thực hiện. Tôi chân thành hy vọng bạn thấy loạt bài này hữu ích và mong muốn được nghe về những hiểu biết mới mà bạn có được từ việc sử dụng các công cụ giúp phân tích và giải quyết các vấn đề về hiệu suất với các ứng dụng Access sử dụng nguồn dữ liệu ODBC. Vui lòng để lại bình luận hoặc yêu cầu thêm thông tin và cảm ơn bạn đã đọc cùng nhau!
Để được hỗ trợ thêm về bất kỳ điều gì liên quan đến Microsoft Access, hãy gọi cho các chuyên gia của chúng tôi theo số 773-809-5456 hoặc gửi email cho chúng tôi theo địa chỉ [email protected].