Tại sao MỤC TIÊU trả lại NULL?


7

Giả sử bạn muốn truy vấn cơ sở dữ liệu để khám phá các loại kích hoạt mà nó chứa. Một cách để làm điều này là sử dụng hàm OBRIPROPERTY trên tất cả các đối tượng kích hoạt trong cơ sở dữ liệu.

Đôi khi, hàm OBOGPROPERTY tạo ra kết quả khó hiểu. Đầu ra của nó dường như phụ thuộc vào bối cảnh cơ sở dữ liệu.

Truy vấn ví dụ sau đây trả về một hàng cho mỗi kích hoạt sysmail trong msdb:

SELECT
  object_id,
  name,
  OBJECTPROPERTY(object_id, 'ExecIsInsertTrigger') AS IsInsertTrigger,
  OBJECTPROPERTY(object_id, 'ExecIsUpdateTrigger') AS IsUpdateTrigger,
  OBJECTPROPERTY(object_id, 'ExecIsDeleteTrigger') AS IsDeleteTrigger
FROM msdb.sys.objects
WHERE
  [type] = 'TR' AND
  name LIKE 'trig_sysmail_%';
GO

Mục đích là để tìm ra hành động DML nào sẽ kích hoạt mỗi kích hoạt. Ví dụ: IsInsertTriggercột chứa 1 nếu kích hoạt được xác định là AFTER INSERTvà 0 khác.

Khi tôi thực hiện truy vấn trong ngữ cảnh của msdb, tập kết quả chứa 0 hoặc 1 trong mỗi cột được tính. Nó trông như thế này:

object_id   name                         IsInsertTrigger IsUpdateTrigger IsDeleteTrigger
----------- ---------------------------- --------------- --------------- ---------------
713105631   trig_sysmail_profile         0               1               0
745105745   trig_sysmail_account         0               1               0
761105802   trig_sysmail_profileaccount  0               1               0
777105859   trig_sysmail_profile_delete  0               0               1
793105916   trig_sysmail_servertype      0               1               0
809105973   trig_sysmail_server          0               1               0
825106030   trig_sysmail_configuration   0               1               0
841106087   trig_sysmail_mailitems       0               1               0
857106144   trig_sysmail_attachments     0               1               0
873106201   trig_sysmail_log             0               1               0

Khi tôi thực hiện truy vấn trong ngữ cảnh chính, tập kết quả chứa NULL trong mỗi cột được tính toán. Nó trông như thế này:

object_id   name                         IsInsertTrigger IsUpdateTrigger IsDeleteTrigger
----------- ---------------------------- --------------- --------------- ---------------
713105631   trig_sysmail_profile         NULL            NULL            NULL
745105745   trig_sysmail_account         NULL            NULL            NULL
761105802   trig_sysmail_profileaccount  NULL            NULL            NULL
777105859   trig_sysmail_profile_delete  NULL            NULL            NULL
793105916   trig_sysmail_servertype      NULL            NULL            NULL
809105973   trig_sysmail_server          NULL            NULL            NULL
825106030   trig_sysmail_configuration   NULL            NULL            NULL
841106087   trig_sysmail_mailitems       NULL            NULL            NULL
857106144   trig_sysmail_attachments     NULL            NULL            NULL
873106201   trig_sysmail_log             NULL            NULL            NULL

MSDN lưu ý rằng hàm OBRIPROPERTY trả về NULL khi:

  1. tên tài sản không hợp lệ.
  2. id đối tượng không hợp lệ.
  3. id là một loại đối tượng không được hỗ trợ cho thuộc tính được chỉ định.
  4. người gọi không có quyền xem siêu dữ liệu của đối tượng.

Tôi có thể loại trừ lý do 1 và 3 vì truy vấn trả về kết quả chính xác trong ngữ cảnh của msdb.

Lúc đầu, tôi nghĩ rằng nó có thể là một vấn đề quyền cơ sở dữ liệu chéo (lý do 4), nhưng tôi là sysadmin trên máy chủ.

Đó là lý do 2, khiến tôi có những câu hỏi sau:

Là id đối tượng không hợp lệ trong một truy vấn cơ sở dữ liệu chéo?

Hàm OBRIPROPERTY của cơ sở dữ liệu nào đang được gọi?

Câu trả lời:


6

MỤC TIÊU là cục bộ của cơ sở dữ liệu truy vấn được chạy nó. Vì vậy, object_idthông qua được giải quyết chống lại master.sys.objects: nhưng object_id đến từmsdb

Vì vậy, ở đây bạn có trường hợp 2.

Trên máy chủ của tôi, tôi có 37 giá trị object_id phù hợp giữa msdbSomeDBOnMyServer. Nhưng tên thì khác.

USE SomeDBOnMyServer
GO
SELECT
  object_id,
  name,
  OBJECT_NAME(object_id)
FROM msdb.sys.objects
WHERE OBJECT_NAME(object_id) <> name

Rõ ràng, tôi có rất nhiều hàng trong đó OBJECT_NAME(object_id)NULL được lọc ở đây


+1 để giải thích rằng id đối tượng là từ một cơ sở dữ liệu và đang được tra cứu trong cơ sở dữ liệu khác. Tôi nghĩ rằng truy vấn đó không trả về hàng nào trong cơ sở dữ liệu của tôi; không có id đối tượng chung.
Iain Samuel McLean Elder

6

Như gbn đã lưu ý, bạn cần chạy truy vấn này trong ngữ cảnh của cơ sở dữ liệu msdb OBJECTPROPERTYđể giải quyết chính xác. Nếu bạn muốn làm cho cơ sở dữ liệu kịch bản của mình không rõ ràng thì bạn có thể viết một truy vấn phức tạp hơn để có được thông tin tương tự:

SELECT 
  t.[object_id], t.name, 
  IsInsertTrigger = MAX(CASE WHEN i.[type] IS NULL THEN 0 ELSE 1 END),
  IsUpdateTrigger = MAX(CASE WHEN u.[type] IS NULL THEN 0 ELSE 1 END),
  IsDeleteTrigger = MAX(CASE WHEN d.[type] IS NULL THEN 0 ELSE 1 END)
FROM msdb.sys.triggers AS t
LEFT OUTER JOIN 
  msdb.sys.trigger_events AS i
  ON t.[object_id] = i.[object_id] AND i.[type] = 1
LEFT OUTER JOIN 
  msdb.sys.trigger_events AS u
  ON t.[object_id] = u.[object_id] AND u.[type] = 2
LEFT OUTER JOIN 
  msdb.sys.trigger_events AS d
  ON t.[object_id] = d.[object_id] AND d.[type] = 3
WHERE t.name LIKE 'trig[_]sysmail[_]%'
GROUP BY t.[object_id], t.name;

+1 cho truy vấn! Tôi không biết về sys.trigger_events. Các tài liệu để sys.triggerskhông đề cập đến nó, nhưng nó liên quan rõ ràng.
Iain Samuel McLean Elder

Và cảm ơn vì đã sửa lỗi tinh vi trong caluse THÍCH của tôi.
Iain Samuel McLean Elder

@isme bạn đã phải thực hiện một số thứ khá sởn gai ốc trong msdb để bị cuốn theo nó, nhưng đó là một thói quen, xin lỗi. :-)
Aaron Bertrand
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.