Sql-Server
視圖可以適應隱式引用使用者的預設架構嗎?
一點背景。我有一個基本應用程序,大多數客戶將其用作標準。然而,一些客戶有小的程式碼和數據庫定制。這些客戶端中的每一個都有自己的分支,維護可能很棘手。
我想將所有這些整合到一個單一的數據庫結構中(不是一個單一的數據庫——我們不是在做多租戶),以便以更統一的方式應用升級。我仍處於概念驗證階段,但我要走的路線是讓標準對象保留在它們目前存在的架構中(主要是 dbo),並讓自定義對象駐留在每個客戶端的架構中。
例如,我可以有 dbo.users 和 client1.users 有一些額外的列。如果我將客戶端的預設架構設置為“client1”,則以下查詢
SELECT * FROM users
將根據連接的登錄名從 client1 模式或 dbo 模式返回數據。這對於我想要實現的目標來說絕對是完美的。
我遇到的問題是視圖。我有很多在 dbo 模式中的視圖,並引用了使用者表。無論我以哪個使用者身份連接到數據庫,這些視圖總是從 dbo.users 中選擇。
所以我猜我的問題是:我可以在視圖中的表前面加上一些變數,比如“DEFAULT”嗎?例如
SELECT u.username, u.email, a.level FROM DEFAULT.users u INNER JOIN DEFAULT.accessLevels a ON u.accessID = a.accessID
如果這是不可能的,而且我完全是在找錯樹,你對我如何實現我打算做的事情有什麼建議嗎?
非常感謝。
創建多個視圖和/或表值函式。除非您建構動態 SQL 來為您執行此操作,否則您無法在不明確指定的情況下覆蓋架構,但您不能在視圖或函式中執行此操作 - 只能在儲存過程中執行。
話雖如此,您可以使用類似的方法來執行此操作,但是如果找不到匹配項或者您正在使用 Windows 組(例如,在 SQL Server 2012 不支持預設架構):
CREATE PROCEDURE dbo.whatever_procedure AS BEGIN SET NOCOUNT ON; DECLARE @sql NVARCHAR(MAX), @s SYSNAME; SELECT @s = d.default_schema_name FROM sys.database_principals AS d LEFT OUTER JOIN sys.server_principals AS s ON d.[sid] = s.[sid] WHERE SUSER_SNAME() IN (d.name, s.name); SELECT @s = COALESCE(@s, N'dbo'); SET @sql = N'SELECT x FROM ' + QUOTENAME(@s) + '.whatever_view_name;'; EXEC sp_executesql @sql; END GO
您可以對此進行測試:
USE tempdb; GO CREATE SCHEMA foo; GO CREATE LOGIN flubat WITH PASSWORD='flubat',CHECK_POLICY = OFF; GO CREATE USER flubat FROM LOGIN flubat WITH DEFAULT_SCHEMA = foo; GO GRANT SELECT ON SCHEMA::foo TO flubat; GO CREATE VIEW dbo.whatever_view_name AS SELECT x = 'dbo'; GO CREATE VIEW foo.whatever_view_name AS SELECT x = 'foo'; GO -- create the above procedure GO GRANT EXEC ON dbo.whatever_procedure TO flubat; GO
然後以您自己的身份執行它,也以
flubat
:EXEC dbo.whatever_procedure; GO EXECUTE AS USER = N'flubat'; GO EXEC dbo.whatever_procedure; GO REVERT;
結果:
x ---- dbo x ---- foo
但就像我說的,這可能很脆弱,我傾向於為每個模式創建一個視圖,或者完全改變設計。