Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Các nguyên tắc cơ bản về biểu thức bảng, Phần 10 - Các thay đổi về chế độ xem, SELECT * và DDL

Là một phần của loạt bài về biểu thức bảng, tháng trước tôi đã bắt đầu giới thiệu các lượt xem. Cụ thể, tôi bắt đầu bao quát các khía cạnh logic của các khung nhìn và so sánh thiết kế của chúng với thiết kế của các bảng và CTE dẫn xuất. Tháng này, tôi sẽ tiếp tục đề cập đến các khía cạnh logic của chế độ xem, tập trung sự chú ý vào các thay đổi của CHỌN * và DDL.

Mã mà tôi sẽ sử dụng trong bài viết này có thể được thực thi trong bất kỳ cơ sở dữ liệu nào, nhưng trong các bản trình diễn của tôi, tôi sẽ sử dụng TSQLV5 — cùng một cơ sở dữ liệu mẫu mà tôi đã sử dụng trong các bài viết trước. Bạn có thể tìm thấy tập lệnh tạo và điền TSQLV5 tại đây và sơ đồ ER của nó tại đây.

Sử dụng SELECT * trong truy vấn bên trong của chế độ xem là một ý tưởng tồi

Trong phần kết luận của bài báo tháng trước, tôi đã đặt ra một câu hỏi là thức ăn cho suy nghĩ. Tôi đã giải thích rằng trước đó trong loạt bài này, tôi đã đưa ra một trường hợp ủng hộ việc sử dụng SELECT * trong các biểu thức bảng bên trong được sử dụng với các bảng dẫn xuất và CTE. Xem Phần 3 của loạt bài này để biết chi tiết nếu bạn cần làm mới bộ nhớ của mình. Sau đó, tôi yêu cầu bạn suy nghĩ xem liệu đề xuất tương tự có còn hợp lệ cho biểu thức bảng bên trong được sử dụng để xác định chế độ xem hay không. Có lẽ tiêu đề của phần này đã là một trò lừa bịp, nhưng tôi sẽ nói ngay rằng với lượt xem, đó thực sự là một ý kiến ​​rất tồi.

Tôi sẽ bắt đầu với các chế độ xem không được xác định bằng thuộc tính SCHEMABINDING, thuộc tính này ngăn các thay đổi DDL có liên quan đối với các đối tượng phụ thuộc và sau đó giải thích cách mọi thứ thay đổi khi bạn sử dụng thuộc tính này.

Tôi sẽ chuyển thẳng đến một ví dụ vì đây sẽ là cách dễ nhất để trình bày lập luận của tôi.

Sử dụng mã sau để tạo một bảng có tên dbo.T1 và một dạng xem được gọi là dbo.V1 dựa trên truy vấn với SELECT * đối với bảng:

 SỬ DỤNG TSQLV5; DROP XEM NẾU TỒN TẠI dbo.V1; DROP TABLE IF TỒN TẠI dbo.T1; ĐI TẠO BẢNG dbo.T1 (keycol INT NOT NULL IDENTITY CONSTRAINT PK_T1 PRIMARY KEY, intcol INT NOT NULL, charcol VARCHAR (10) NOT NULL); CHÈN VÀO CÁC GIÁ TRỊ dbo.T1 (intcol, charcol) (10, 'A'), (20, 'B'); ĐI TẠO HOẶC CẢNH BÁO XEM dbo.V1AS CHỌN * TỪ dbo.T1; ĐI 

Quan sát bảng hiện có các cột keycol, intcol và charcol.

Sử dụng mã sau để truy vấn chế độ xem:

 CHỌN * TỪ dbo.V1; 

Bạn nhận được kết quả sau:

 keycol intcol charcol ------------- ---------------- 1 10 A2 20 B 

Không có gì quá đặc biệt ở đây.

Khi bạn tạo dạng xem, SQL Server ghi lại thông tin siêu dữ liệu trong một số đối tượng danh mục. Nó ghi lại một số thông tin chung mà bạn có thể truy vấn qua sys.views, định nghĩa chế độ xem mà bạn có thể truy vấn thông qua sys.sql_modules, thông tin cột mà bạn có thể truy vấn qua sys.columns và nhiều thông tin khác có sẵn thông qua các đối tượng khác. Điều cũng liên quan đến cuộc thảo luận của chúng tôi là SQL Server cho phép bạn kiểm soát quyền truy cập đối với các chế độ xem. Điều tôi muốn cảnh báo bạn khi sử dụng SELECT * trong biểu thức bảng bên trong của chế độ xem, là điều gì có thể xảy ra khi các thay đổi DDL được áp dụng cho các đối tượng phụ thuộc cơ bản.

Sử dụng mã sau để tạo người dùng có tên là user1 và cấp cho người dùng quyền chọn các cột keycol và intcol từ chế độ xem, nhưng không phải charcol:

 DROP USER NẾU TỒN TẠI người dùng1; TẠO NGƯỜI DÙNG 1 người dùng KHÔNG ĐĂNG NHẬP; CẤP CHỌN TRÊN dbo.V1 (keycol, intcol) CHO người dùng1; 

Tại thời điểm này, hãy kiểm tra một số siêu dữ liệu được ghi lại liên quan đến chế độ xem của chúng tôi. Sử dụng mã sau để trả về mục nhập đại diện cho chế độ xem từ sys.views:

 CHỌN SCHEMA_NAME (schema_id) AS tên lược đồ, tên, object_id, type_descFROM sys.viewsWHERE object_id =OBJECT_ID (N'dbo.V1 '); 

Mã này tạo ra kết quả sau:

 tên lược đồ object_id type_desc ----------- ----------- ----------- dbo V1 130099504 XEM  

Sử dụng mã sau để lấy định nghĩa chế độ xem từ sys.modules:

 CHỌN định nghĩa TỪ sys.sql_modulesWHERE object_id =OBJECT_ID (N'dbo.V1 '); 

Một tùy chọn khác là sử dụng hàm OBJECT_DEFINITION như sau:

 CHỌN OBJECT_DEFINITION (OBJECT_ID (N'dbo.V1 ')); 

Bạn nhận được kết quả sau:

 TẠO CHỌN CHẾ ĐỘ XEM dbo.V1AS * TỪ dbo.T1; 

Sử dụng mã sau để truy vấn định nghĩa cột của chế độ xem từ sys.columns:

 CHỌN tên AS column_name, column_id, TYPE_NAME (system_type_id) AS data_typeFROM sys.columnsWHERE object_id =OBJECT_ID (N'dbo.V1 '); 

Như mong đợi, bạn nhận được thông tin về ba cột keycol, intcol và charcol của chế độ xem:

 column_name column_id data_type ------------- ---------------- keycol 1 intintcol 2 intcharcol 3 varchar 

Quan sát các ID cột (vị trí thứ tự) được liên kết với các cột.

Bạn có thể nhận được thông tin tương tự bằng cách truy vấn chế độ xem giản đồ thông tin tiêu chuẩn INFORMATION_SCHEMA.COLUMNS, như sau:

 SELECT COLUMN_NAME, ORDINAL_POSITION, DATA_TYPEFROM INFORMATION_SCHEMA.COLUMNSWHERE TABLE_SCHEMA =N'dbo 'AND TABLE_NAME =N'V1'; 

Để nhận thông tin phụ thuộc của chế độ xem (các đối tượng mà nó đề cập đến), bạn có thể truy vấn sys.dm_sql_referenced_entities, như sau:

 CHỌN OBJECT_NAME (reference_id) AS reference_object, reference_minor_id, COL_NAME (reference_id, reference_minor_id) AS column_nameFROM sys.dm_sql_referenced_entities (N'dbo.V1 ', N'OBJECT'); 

Bạn sẽ tìm thấy sự phụ thuộc trên bảng T1 và trên ba cột của nó:

 reference_object reference_minor_id column_name --------------------------------- ---- T1 0 NULLT1 1 keycolT1 2 intcolT1 3 charcol 

Như bạn có thể đoán, giá trị reference_minor_id cho các cột là ID cột bạn đã thấy trước đó.

Nếu bạn muốn nhận quyền của user1 đối với V1, bạn có thể truy vấn sys.database_permissions, như sau:

 SELECT OBJECT_NAME (major_id) AS reference_object, small_id, COL_NAME (major_id, minor_id) AS column_name, allow_nameFROM sys.database_permissionsWHERE major_id =OBJECT_ID (N'dbo.V1 ') VÀ Grantee_principal_id =USER_ID (N'user1');  

Mã này tạo ra kết quả sau, khẳng định rằng thực sự user1 chỉ có quyền chọn đối với keycol và intcol, chứ không phải đối với charcol:

 reference_object small_id column_name allow_name --------------------------------- -------------- V1 1 keycol SELECTV1 2 intcol SELECT 

Một lần nữa, giá trị nhỏ_id là ID cột mà bạn đã thấy trước đó. Người dùng của chúng tôi, user1, có quyền đối với các cột có ID là 1 và 2.

Tiếp theo, hãy chạy mã sau để mạo danh user1 và thử truy vấn tất cả các cột của V1:

 THỰC HIỆN AS USER =N'user1 '; CHỌN * TỪ dbo.V1; 

Như bạn mong đợi, bạn gặp lỗi quyền do thiếu quyền truy vấn charcol:

Msg 230, Mức 14, Trạng thái 1, Dòng 141
Quyền SELECT bị từ chối trên cột 'charcol' của đối tượng 'V1', cơ sở dữ liệu 'TSQLV5', lược đồ 'dbo'.

Chỉ thử truy vấn keycol và intcol:

 CHỌN keycol, intcol FROM dbo.V1; 

Lần này truy vấn chạy thành công, tạo ra kết quả sau:

 keycol intcol ----------- ----------- 1 102 20 

Không có gì ngạc nhiên cho đến nay.

Chạy mã sau để hoàn nguyên về người dùng ban đầu của bạn:

 REVERT; 

Bây giờ, hãy áp dụng một vài thay đổi cấu trúc cho bảng bên dưới dbo.T1. Chạy đoạn mã sau để thêm hai cột được gọi là datecol và binarycol, sau đó thả vào intcol:

 ALTER TABLE dbo.T1 ADD datecol DATE NOT NULL DEFAULT ('99991231'), binarycol VARBINARY (3) NOT NULL DEFAULT (0x112233); ALTER TABLE dbo.T1 DROP COLUMN intcol; 

SQL Server đã không từ chối các thay đổi cấu trúc đối với các cột được tham chiếu bởi dạng xem vì dạng xem không được tạo bằng thuộc tính SCHEMABINDING. Bây giờ, để bắt. Tại thời điểm này, SQL Server chưa làm mới thông tin siêu dữ liệu của chế độ xem trong các đối tượng danh mục khác nhau.

Sử dụng mã sau để truy vấn chế độ xem, vẫn với người dùng ban đầu của bạn (chưa phải là user1):

 CHỌN * TỪ dbo.V1; 

Bạn nhận được kết quả sau:

 keycol intcol charcol ------------- ---------------- 1 A 9999-12-312 B 9999-12-31 

Lưu ý rằng intcol thực sự trả về nội dung của charcol và charcol trả về nội dung của datecol. Hãy nhớ rằng, không có intcol trong bảng nữa nhưng có datecol. Ngoài ra, bạn không lấy lại binarycol cột mới.

Để thử và tìm hiểu điều gì đang xảy ra, hãy sử dụng mã sau để truy vấn siêu dữ liệu cột của chế độ xem:

 CHỌN tên AS column_name, column_id, TYPE_NAME (system_type_id) AS data_typeFROM sys.columnsWHERE object_id =OBJECT_ID (N'dbo.V1 '); 

Mã này tạo ra kết quả sau:

 column_name column_id data_type ------------- ---------------- keycol 1 intintcol 2 intcharcol 3 varchar 

Như bạn có thể thấy, siêu dữ liệu của chế độ xem vẫn chưa được làm mới. Bạn có thể xem intcol là cột ID 2 và charcol là cột ID 3. Trên thực tế, intcol không còn tồn tại nữa, charcol được cho là cột 2 và datecol được cho là cột 3.

Hãy kiểm tra xem có bất kỳ thay đổi nào với thông tin về quyền hay không:

 SELECT OBJECT_NAME (major_id) AS reference_object, small_id, COL_NAME (major_id, minor_id) AS column_name, allow_nameFROM sys.database_permissionsWHERE major_id =OBJECT_ID (N'dbo.V1 ') VÀ Grantee_principal_id =USER_ID (N'user1');  

Bạn nhận được kết quả sau:

 reference_object small_id column_name allow_name --------------------------------- -------------- V1 1 keycol SELECTV1 2 intcol SELECT 

Thông tin quyền cho thấy rằng user1 có quyền đối với cột 1 và 2 trong chế độ xem. Tuy nhiên, mặc dù siêu dữ liệu cho rằng cột 2 được gọi là intcol, nó thực sự được ánh xạ tới charcol trong T1 trong thực tế. Điều đó thật nguy hiểm vì người dùng1 không được phép có quyền truy cập vào charcol. Điều gì sẽ xảy ra nếu trong đời thực, cột này chứa thông tin nhạy cảm như mật khẩu.

Hãy đóng giả user1 một lần nữa và truy vấn tất cả các cột chế độ xem:

 THỰC HIỆN AS USER ='user1'; CHỌN * TỪ dbo.V1; 

Bạn gặp lỗi về quyền cho biết bạn không có quyền truy cập vào charcol:

Msg 230, Mức 14, Trạng thái 1, Dòng 211
Quyền SELECT bị từ chối trên cột 'charcol' của đối tượng 'V1', cơ sở dữ liệu 'TSQLV5', lược đồ 'dbo'.

Tuy nhiên, hãy xem điều gì sẽ xảy ra khi bạn yêu cầu rõ ràng keycol và intcol:

 CHỌN keycol, intcol FROM dbo.V1; 

Bạn nhận được kết quả sau:

 keycol intcol ------------- 1 A2 B 

Truy vấn này thành công, chỉ nó trả về nội dung của charcol dưới intcol. Người dùng của chúng tôi, user1, không được phép có quyền truy cập vào thông tin này. Rất tiếc!

Tại thời điểm này, hãy hoàn nguyên về người dùng ban đầu bằng cách chạy mã sau:

 REVERT; 

Làm mới mô-đun SQL

Bạn có thể thấy rõ rằng sử dụng SELECT * trong biểu thức bảng bên trong của chế độ xem là một ý tưởng tồi. Nhưng nó không chỉ có vậy. Nói chung, bạn nên làm mới siêu dữ liệu của chế độ xem sau mỗi lần thay đổi DDL đối với các đối tượng và cột được tham chiếu. Bạn có thể làm như vậy bằng cách sử dụng sp_refreshview hoặc sp_refreshmodule tổng quát hơn, như sau:

 EXEC sys.sp_refreshsqlmodule N'dbo.V1 '; 

Truy vấn lại chế độ xem, bây giờ siêu dữ liệu của nó đã được làm mới:

 CHỌN * TỪ dbo.V1; 

Lần này bạn nhận được kết quả mong đợi:

 keycol charcol datecol binarycol ------------- ---------------- 1 A 9999 -12-31 0x1122332 B 9999-12-31 0x112233 

Cột charcol được đặt tên chính xác và hiển thị dữ liệu chính xác; bạn không thấy intcol và bạn thấy các cột datecol và binarycol mới.

Truy vấn siêu dữ liệu cột của chế độ xem:

 CHỌN tên AS column_name, column_id, TYPE_NAME (system_type_id) AS data_typeFROM sys.columnsWHERE object_id =OBJECT_ID (N'dbo.V1 '); 

Đầu ra hiện hiển thị thông tin siêu dữ liệu cột chính xác:

 column_name column_id data_type ------------- ---------------- keycol 1 intcharcol 2 varchardatecol 3 datebinarycol 4 varbinary  

Truy vấn quyền của user1 đối với chế độ xem:

 SELECT OBJECT_NAME (major_id) AS reference_object, small_id, COL_NAME (major_id, minor_id) AS column_name, allow_nameFROM sys.database_permissionsWHERE major_id =OBJECT_ID (N'dbo.V1 ') VÀ Grantee_principal_id =USER_ID (N'user1');  

Bạn nhận được kết quả sau:

 reference_object small_id column_name allow_name --------------------------------- -------------- V1 1 móc khóa CHỌN 

Thông tin cho phép bây giờ là chính xác. Người dùng của chúng tôi, user1, chỉ có quyền chọn keycol và thông tin quyền đối với intcol đã bị xóa.

Để đảm bảo tất cả đều tốt, hãy kiểm tra điều này bằng cách đóng giả user1 và truy vấn chế độ xem:

 THỰC HIỆN AS USER ='user1'; CHỌN * TỪ dbo.V1; 

Bạn gặp hai lỗi quyền do thiếu quyền đối với datecol và binarycol:

Msg 230, Mức 14, Trạng thái 1, Dòng 281
Quyền SELECT bị từ chối trên cột 'datecol' của đối tượng 'V1', cơ sở dữ liệu 'TSQLV5', lược đồ 'dbo'.

Msg 230, Mức 14, Trạng thái 1, Dòng 281
Quyền SELECT bị từ chối trên cột 'binarycol' của đối tượng 'V1', cơ sở dữ liệu 'TSQLV5', lược đồ 'dbo'.

Thử truy vấn keycol và intcol:

 CHỌN keycol, intcol FROM dbo.V1; 

Lần này, lỗi cho biết chính xác rằng không có cột nào được gọi là intcol:

Bản tin thứ 207, mức 16, trạng thái 1, dòng 279

Tên cột không hợp lệ 'intcol'.

Chỉ truy vấn intcol:

 CHỌN móc khóa TỪ dbo.V1; 

Truy vấn này chạy thành công, tạo ra kết quả sau:

 keycol ----------- 12 

Tại thời điểm này, hoàn nguyên về người dùng ban đầu của bạn bằng cách chạy mã sau:

 REVERT; 

Có đủ để tránh SELECT * và sử dụng các tên cột rõ ràng không?

Nếu bạn làm theo một phương pháp không có CHỌN * trong biểu thức bảng bên trong của chế độ xem, thì điều này có đủ để giúp bạn tránh gặp rắc rối không? Chà, hãy xem…

Sử dụng mã sau để tạo lại bảng và chế độ xem, chỉ lần này liệt kê các cột một cách rõ ràng trong truy vấn bên trong của chế độ xem:

 DROP XEM NẾU TỒN TẠI dbo.V1; BẢNG XÓA NẾU TỒN TẠI dbo.T1; ĐI TẠO BẢNG dbo.T1 (keycol INT NOT NULL IDENTITY CONSTRAINT PK_T1 PRIMARY KEY, intcol INT NOT NULL, charcol VARCHAR (10) NOT NULL); CHÈN VÀO CÁC GIÁ TRỊ dbo.T1 (intcol, charcol) (10, 'A'), (20, 'B'); ĐI TẠO HOẶC CẢNH BÁO XEM dbo.V1AS CHỌN keycol, intcol, charcol TỪ dbo.T1; ĐI 

Truy vấn chế độ xem:

 CHỌN * TỪ dbo.V1; 

Bạn nhận được kết quả sau:

 keycol intcol charcol ------------- ---------------- 1 10 A2 20 B 

Một lần nữa, cấp quyền cho user1 để chọn keycol và intcol:

 CẤP CHỌN TRÊN dbo.V1 (keycol, intcol) CHO user1; 

Tiếp theo, áp dụng các thay đổi cấu trúc tương tự như bạn đã làm trước đây:

 ALTER TABLE dbo.T1 ADD datecol DATE NOT NULL DEFAULT ('99991231'), binarycol VARBINARY (3) NOT NULL DEFAULT (0x112233); ALTER TABLE dbo.T1 DROP COLUMN intcol; 

Quan sát rằng SQL Server đã chấp nhận những thay đổi này, mặc dù dạng xem có tham chiếu rõ ràng đến intcol. Một lần nữa, đó là do chế độ xem được tạo mà không có tùy chọn SCHEMABINDING.

Truy vấn chế độ xem:

 CHỌN * TỪ dbo.V1; 

Tại thời điểm này, SQL Server tạo ra lỗi sau:

Msg 207, Mức 16, Trạng thái 1, Quy trình V1, Dòng 5 [Dòng Bắt đầu Hàng loạt 344]
Tên cột không hợp lệ 'intcol'.

Msg 4413, Mức 16, Trạng thái 1, Dòng 345
Không thể sử dụng chế độ xem hoặc chức năng 'dbo.V1' do lỗi liên kết.

SQL Server đã cố gắng giải quyết tham chiếu intcol trong dạng xem và tất nhiên là không thành công.

Nhưng điều gì sẽ xảy ra nếu kế hoạch ban đầu của bạn là bỏ intcol và sau đó thêm lại nó? Sử dụng mã sau để thêm lại, sau đó truy vấn chế độ xem:

 ALTER TABLE dbo.T1 ADD intcol INT NOT NULL DEFAULT (0); CHỌN * TỪ dbo.V1; 

Mã này tạo ra kết quả sau:

 keycol intcol charcol ------------- ---------------- 1 0 A2 0 B 

Kết quả có vẻ đúng.

Làm thế nào về việc truy vấn chế độ xem với tư cách là user1? Hãy thử nó:

 THỰC HIỆN AS USER ='user1'; CHỌN * TỪ dbo.V1; 

Khi truy vấn tất cả các cột, bạn nhận được lỗi mong đợi do thiếu quyền đối với charcol:

Msg 230, Mức 14, Trạng thái 1, Dòng 367
Quyền SELECT bị từ chối trên cột 'charcol' của đối tượng 'V1', cơ sở dữ liệu 'TSQLV5', lược đồ 'dbo'.

Truy vấn keycol và intcol một cách rõ ràng:

 CHỌN keycol, intcol FROM dbo.V1; 

Bạn nhận được kết quả sau:

 keycol intcol ----------- ----------- 1 02 0 

Có vẻ như mọi thứ đều theo thứ tự do bạn không sử dụng SELECT * trong truy vấn bên trong của chế độ xem, mặc dù bạn không làm mới siêu dữ liệu của chế độ xem. Tuy nhiên, có thể là một phương pháp hay để làm mới siêu dữ liệu của chế độ xem sau khi DDL thay đổi thành các đối tượng và cột được tham chiếu ở bên an toàn.

Tại thời điểm này, hãy hoàn nguyên về người dùng ban đầu của bạn bằng cách chạy mã sau:

 REVERT; 

SCHEMABINDING

Sử dụng thuộc tính chế độ xem SCHEMABINDING, bạn có thể tránh được rất nhiều rắc rối đã nói ở trên. Một trong những chìa khóa để tránh rắc rối mà bạn đã thấy trước đó là không sử dụng SELECT * trong truy vấn bên trong của chế độ xem. Nhưng cũng có vấn đề về thay đổi cấu trúc đối với các đối tượng phụ thuộc, chẳng hạn như giảm các cột được tham chiếu, vẫn có thể dẫn đến lỗi khi truy vấn chế độ xem. Sử dụng thuộc tính chế độ xem SCHEMABINDING, bạn sẽ không được phép sử dụng SELECT * trong truy vấn bên trong. Hơn nữa, SQL Server sẽ từ chối nỗ lực áp dụng các thay đổi DDL có liên quan cho các đối tượng và cột phụ thuộc. Về mặt liên quan, ý tôi là những thay đổi như bỏ bảng hoặc cột được tham chiếu. Việc thêm một cột vào bảng được tham chiếu rõ ràng không phải là một vấn đề, vì vậy SCHEMABINDING không ngăn chặn sự thay đổi như vậy.

Để chứng minh điều này, hãy sử dụng mã sau để tạo lại bảng và chế độ xem, với SCHEMABINDING trong định nghĩa chế độ xem:

 DROP XEM NẾU TỒN TẠI dbo.V1; BẢNG XÓA NẾU TỒN TẠI dbo.T1; ĐI TẠO BẢNG dbo.T1 (keycol INT NOT NULL IDENTITY CONSTRAINT PK_T1 PRIMARY KEY, intcol INT NOT NULL, charcol VARCHAR (10) NOT NULL); CHÈN VÀO CÁC GIÁ TRỊ dbo.T1 (intcol, charcol) (10, 'A'), (20, 'B'); ĐI TẠO HOẶC CẢNH BÁO XEM dbo.V1 VỚI CHỌN SCHEMABINDINGAS * TỪ dbo.T1; ĐI 

Bạn gặp lỗi:

Msg 1054, Mức 15, Trạng thái 6, Thủ tục V1, Dòng 5 [Dòng Bắt đầu Hàng loạt 387]
Cú pháp '*' không được phép trong các đối tượng liên kết lược đồ.

Khi sử dụng SCHEMABINDING, bạn không được phép sử dụng SELECT * trong biểu thức bảng bên trong của chế độ xem.

Hãy thử tạo lại chế độ xem, chỉ lần này với danh sách cột rõ ràng:

 TẠO HOẶC ALTER XEM dbo.V1 VỚI SCHEMABINDINGAS CHỌN keycol, intcol, charcol TỪ dbo.T1; ĐI 

Lần này chế độ xem được tạo thành công.

Cấp quyền cho user1 trên keycol và intcol:

 CẤP CHỌN TRÊN dbo.V1 (keycol, intcol) CHO user1; 

Tiếp theo, cố gắng áp dụng các thay đổi cấu trúc cho bảng. Đầu tiên, hãy thêm một vài cột:

 ALTER TABLE dbo.T1 THÊM dữ liệu NGÀY KHÔNG ĐẦY ĐỦ ĐỊNH NGHĨA ('99991231'), binarycol VARBINARY (3) NOT NULL DEFAULT (0x112233); 

Thêm cột không phải là vấn đề vì chúng không thể là một phần của chế độ xem liên kết giản đồ hiện có, vì vậy mã này hoàn thành thành công.

Cố gắng bỏ intcol cột:

 BẢNG ALTER dbo.T1 DROP COLUMN intcol; 

Bạn gặp lỗi sau:

Msg 5074, Mức 16, Trạng thái 1, Dòng 418
Đối tượng 'V1' phụ thuộc vào cột 'intcol'.

Msg 4922, Mức 16, Trạng thái 9, Dòng 418
ALTER TABLE DROP COLUMN intcol không thành công vì một hoặc nhiều đối tượng truy cập vào cột này.

Việc giảm hoặc thay đổi các cột được tham chiếu không được phép khi tồn tại các đối tượng liên kết giản đồ.

Nếu bạn vẫn cần bỏ intcol, trước tiên bạn sẽ phải bỏ chế độ xem tham chiếu có giới hạn giản đồ, áp dụng thay đổi, sau đó tạo lại chế độ xem và gán lại quyền, như sau:

 DROP XEM NẾU TỒN TẠI dbo.V1; ĐI BẢNG ALTER dbo.T1 DROP COLUMN intcol; ĐI TẠO HOẶC ALTER XEM dbo.V1 VỚI SCHEMABINDINGAS CHỌN keycol, charcol, datecol, binarycol TỪ dbo.T1; ĐI CẤP CHỌN TRÊN dbo. V1 (keycol, datecol, binarycol) ĐẾN người dùng1; ĐI 

Tất nhiên tại thời điểm này, không cần phải làm mới định nghĩa chế độ xem, vì bạn đã tạo lại định nghĩa đó.

Bây giờ bạn đã kiểm tra xong, hãy chạy mã sau để dọn dẹp:

 DROP XEM NẾU TỒN TẠI dbo.V1; BẢNG XÓA NẾU TỒN TẠI dbo.T1; XÓA NGƯỜI DÙNG NẾU TỒN TẠI người dùng1; 

Tóm tắt

Sử dụng SELECT * trong biểu thức bảng bên trong của chế độ xem là một ý tưởng rất tồi. Sau khi các thay đổi cấu trúc được áp dụng cho các đối tượng được tham chiếu, bạn có thể nhận được tên cột không chính xác và thậm chí cho phép người dùng truy cập vào dữ liệu mà họ không được phép có quyền truy cập. Thực tiễn quan trọng là liệt kê rõ ràng các tên cột được tham chiếu.

Sử dụng SCHEMABINDING trong định nghĩa dạng xem, bạn buộc phải liệt kê tên cột một cách rõ ràng và các thay đổi cấu trúc có liên quan đối với các đối tượng phụ thuộc bị SQL Server từ chối. Do đó, có vẻ như việc tạo chế độ xem bằng SCHEMBINDING luôn là một ý tưởng hay. Tuy nhiên, có một cảnh báo với tùy chọn này. Như bạn đã thấy, việc áp dụng các thay đổi cấu trúc cho các đối tượng được tham chiếu khi sử dụng SCHEMBINDING sẽ trở thành một quá trình lâu hơn, phức tạp hơn. Nó đặc biệt có thể là một vấn đề trong các hệ thống phải có tính sẵn sàng rất cao. Hãy tưởng tượng rằng bạn cần thay đổi một cột được định nghĩa là VARCHAR (50) thành VARCHAR (60). Đó không phải là thay đổi được phép nếu có một chế độ xem được xác định bằng SCHEMABINDING tham chiếu đến cột này. Hệ quả của việc loại bỏ một loạt các chế độ xem tham chiếu, có thể được tham chiếu bởi các chế độ xem khác, v.v., có thể gây ra vấn đề cho hệ thống. Nói tóm lại, không phải lúc nào các công ty chỉ áp dụng một chính sách nói rằng SCHEMABINDING nên được sử dụng cho tất cả các đối tượng hỗ trợ nó. Tuy nhiên, việc áp dụng chính sách không sử dụng SELECT * trong các truy vấn bên trong của chế độ xem sẽ đơn giản hơn.

Còn rất nhiều điều khác để khám phá về các chế độ xem. Sẽ được tiếp tục vào tháng sau…


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ký hiệu chân chim

  2. Salesforce SOQL từ Windows PowerShell

  3. Cơ sở dữ liệu Greenplum là gì? Giới thiệu về Cơ sở dữ liệu lớn

  4. Intel có bị diệt vong trong không gian CPU máy chủ không?

  5. Giới thiệu về xử lý không đồng bộ với Service Broker