Nếu bạn cần sử dụng OBJECT_NAME()
chức năng lấy tên của một đối tượng từ một cơ sở dữ liệu khác trong SQL Server, bạn có thể gặp sự cố nếu không biết nó hoạt động như thế nào.
Bạn có thể biết rằng OBJECT_NAME()
chấp nhận một object_id
đối số cho SQL Server biết đối tượng nào cần lấy tên.
Điều bạn có thể biết hoặc có thể không biết, là hàm này cũng chấp nhận một database_id
tùy chọn đối số cho SQL Server biết cơ sở dữ liệu nào object_id
thuộc về.
Theo mặc định, SQL Server giả định rằng object_id
là trong bối cảnh của cơ sở dữ liệu hiện tại. Trong trường hợp này, một truy vấn tham chiếu đến một object_id
trong cơ sở dữ liệu khác sẽ trả về kết quả NULL hoặc (thậm chí tệ hơn) không chính xác.
Ví dụ 1 - Truy vấn cục bộ (từ Cơ sở dữ liệu hiện tại)
Đầu tiên, đây là một truy vấn cục bộ trả về tên đối tượng từ cơ sở dữ liệu hiện tại:
USE Music; SELECT name AS [Foreign Key], OBJECT_NAME(parent_object_id) AS [Parent Object Name], OBJECT_NAME(referenced_object_id) AS [Referenced Object Name] FROM Music.sys.foreign_keys WHERE name = 'FK_Artists_Country';
Kết quả:
Changed database context to 'Music'. +--------------------+----------------------+--------------------------+ | Foreign Key | Parent Object Name | Referenced Object Name | |--------------------+----------------------+--------------------------| | FK_Artists_Country | Artists | Country | +--------------------+----------------------+--------------------------+ (1 row affected)
Những kết quả này là chính xác.
Đây không phải là một truy vấn cơ sở dữ liệu chéo. Đây chỉ là một ví dụ cho thấy cách hàm này được sử dụng khi lấy tên của một đối tượng từ cơ sở dữ liệu hiện tại.
Ví dụ 2 - Truy vấn Cơ sở dữ liệu chéo có KẾT QUẢ SAI!
Bây giờ, đây là một truy vấn cơ sở dữ liệu chéo tạo ra kết quả không chính xác.
USE WideWorldImportersDW; SELECT name AS [Foreign Key], OBJECT_NAME(parent_object_id) AS [Parent Object Name], OBJECT_NAME(referenced_object_id) AS [Referenced Object Name] FROM Music.sys.foreign_keys WHERE name = 'FK_Artists_Country';
Kết quả:
Changed database context to 'WideWorldImportersDW'. +--------------------+----------------------+-----------------------------+ | Foreign Key | Parent Object Name | Referenced Object Name | |--------------------+----------------------+-----------------------------| | FK_Artists_Country | CityKey | PK_Dimension_Payment_Method | +--------------------+----------------------+-----------------------------+ (1 row affected)
Tất cả những gì tôi đã làm là chuyển sang một cơ sở dữ liệu khác, sau đó chạy lại cùng một truy vấn.
Bạn sẽ nhận thấy rằng FROM
của tôi mệnh đề sử dụng tên ba phần để chỉ định tên của cơ sở dữ liệu (Music
). Điều này cho phép tìm thấy khóa ngoại chính xác. Tuy nhiên, điều này là không đủ để ngăn sự cố xảy ra.
Hóa ra, WideWorldImportersDW
cơ sở dữ liệu có các đối tượng có cùng object_id
được sử dụng trong Music
cơ sở dữ liệu. Chỉ có một vấn đề là chúng là những đối tượng hoàn toàn khác nhau, với những cái tên khác nhau. Vì vậy, kết quả ở hai cột cuối cùng là không có thật. Đây là tên của các đối tượng sai, trên cơ sở dữ liệu sai. Truy vấn cơ sở dữ liệu chéo của tôi đã bị đứt dây và trả về sai đối tượng!
Điều này đặc biệt nguy hiểm, vì nếu tôi không chú ý, những kết quả này có vẻ ổn. Rốt cuộc, tôi không gặp lỗi.
Nếu các ID đối tượng này không tồn tại trong cơ sở dữ liệu này, có lẽ tôi sẽ nhận được giá trị NULL (điều này có thể giúp dễ dàng phát hiện có điều gì đó không ổn với kết quả).
Dù bằng cách nào, kết quả chỉ là sai .
Ví dụ 3 - Truy vấn Cơ sở dữ liệu chéo với kết quả ĐÚNG
Để sửa ví dụ trước (mà không thay đổi cơ sở dữ liệu hiện tại), chúng tôi cần cung cấp ID của cơ sở dữ liệu mà chúng tôi muốn có tên của đối tượng.
Như thế này:
USE WideWorldImportersDW; SELECT name AS [Foreign Key], OBJECT_NAME(parent_object_id, 5) AS [Parent Object Name], OBJECT_NAME(referenced_object_id, 5) AS [Referenced Object Name] FROM Music.sys.foreign_keys WHERE name = 'FK_Artists_Country';
Kết quả:
Changed database context to 'WideWorldImportersDW'. +--------------------+----------------------+--------------------------+ | Foreign Key | Parent Object Name | Referenced Object Name | |--------------------+----------------------+--------------------------| | FK_Artists_Country | Artists | Country | +--------------------+----------------------+--------------------------+ (1 row affected)
Xin nhắc lại, chỉ cần nói rõ, cơ sở dữ liệu hiện tại là WideWorldImportersDW
, nhưng các đối tượng nằm trên một cơ sở dữ liệu khác có tên là Music
, có ID cơ sở dữ liệu là 5.
Ví dụ 4 - Cách lấy ID cơ sở dữ liệu
Rất có thể bạn sẽ không biết ID của cơ sở dữ liệu nằm ngoài đầu bạn. Bạn có thể sẽ biết tên của cơ sở dữ liệu, nhưng không biết ID của nó.
May mắn thay, bạn có thể sử dụng DB_ID()
chức năng trả về ID của cơ sở dữ liệu, dựa trên tên của nó.
Do đó, chúng ta có thể sửa đổi ví dụ trước như sau:
USE WideWorldImportersDW; SELECT name AS [Foreign Key], OBJECT_NAME(parent_object_id, DB_ID('Music')) AS [Parent Object Name], OBJECT_NAME(referenced_object_id, DB_ID('Music')) AS [Referenced Object Name] FROM Music.sys.foreign_keys WHERE name = 'FK_Artists_Country';
Kết quả:
Changed database context to 'WideWorldImportersDW'. +--------------------+----------------------+--------------------------+ | Foreign Key | Parent Object Name | Referenced Object Name | |--------------------+----------------------+--------------------------| | FK_Artists_Country | Artists | Country | +--------------------+----------------------+--------------------------+ (1 row affected)