Sql-Server

視圖可以適應隱式引用使用者的預設架構嗎?

  • August 21, 2015

一點背景。我有一個基本應用程序,大多數客戶將其用作標準。然而,一些客戶有小的程式碼和數據庫定制。這些客戶端中的每一個都有自己的分支,維護可能很棘手。

我想將所有這些整合到一個單一的數據庫結構中(不是一個單一的數據庫——我們不是在做多租戶),以便以更統一的方式應用升級。我仍處於概念驗證階段,但我要走的路線是讓標準對象保留在它們目前存在的架構中(主要是 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

但就像我說的,這可能很脆弱,我傾向於為每個模式創建一個視圖,或者完全改變設計。

引用自:https://dba.stackexchange.com/questions/40851