同じテーブルセットを持つ数千のスキーマがあり、各ユーザーにはデフォルトのスキーマがあります。しかし、すべてのスキーマに単一のストアドプロシージャのコピーを作成したくありません。単一のストアドプロシージャがユーザー固有のスキーマのテーブルにアクセスできますか。
これをテストするためにテストプロジェクトを作成しましたが、テーブルが見つからないためエラーが発生しています
create Database PermissionsTest
-- Create user1 and UserSchema1 and assign permissions
CREATE LOGIN [User1] WITH PASSWORD=N'User1'
GO
CREATE USER [User1] FOR LOGIN [User1] WITH DEFAULT_SCHEMA=[UserSchema1]
GO
ALTER LOGIN [User1] Enable
go
CREATE SCHEMA [UserSchema1] AUTHORIZATION [User1]
GO
-- Create user2 and UserSchema2 and assign permissions
CREATE LOGIN [User2] WITH PASSWORD=N'User2'
GO
CREATE USER [User2] FOR LOGIN [User2] WITH DEFAULT_SCHEMA=[UserSchema2]
GO
ALTER LOGIN [User2] Enable
go
CREATE SCHEMA [UserSchema2] AUTHORIZATION [User2]
GO
-- Create StoredProcedure Schema and creating the role to execute on this schema
CREATE ROLE [ExecuteSprocsOnStoredProcsSchema] AUTHORIZATION [dbo]
GO
ALTER AUTHORIZATION ON role::ExecuteSprocsOnStoredProcsSchema TO User1;
GO
Create Schema [StoredProcedures] AUTHORIZATION [ExecuteSprocsOnStoredProcsSchema]
Go
EXEC sp_addrolemember N'ExecuteSprocsOnStoredProcsSchema', N'User1'
GO
EXEC sp_addrolemember N'ExecuteSprocsOnStoredProcsSchema', N'User2'
Go
-- GRANT Execute ON SCHEMA :: StoredProcedures TO ExecuteSprocsOnStoredProcsSchema
GRANT CONNECT TO [User1]
Grant Connect to [User2]
grant SELECT ON SCHEMA::[dbo] TO [User1]
GO
grant SELECT ON SCHEMA::[dbo] TO [User2]
GO
----------------- Database data side changes ---------------
USE PermissionsTest
GO
CREATE TABLE [dbo].[StaticTable](
[pkcol] [int] IDENTITY(1,1) NOT NULL,
[col1] [int] NULL,
PRIMARY KEY CLUSTERED ([pkcol])
)
GO
insert into StaticTable values (420);
-- drop table [UserSchema2].[Table1]
CREATE TABLE [UserSchema1].[Table1](
[pkcol] [int] IDENTITY(1,1) NOT NULL,
[col1] [varchar](max) NULL,
PRIMARY KEY CLUSTERED ([pkcol])
)
GO
CREATE TABLE [UserSchema2].[Table1](
[pkcol] [int] IDENTITY(1,1) NOT NULL,
[col1] [varchar](max) NULL,
PRIMARY KEY CLUSTERED ([pkcol])
)
GO
Create Procedure [StoredProcedures].[Insert_Table1]
as
begin
Insert into table1 values (newID());
Insert into table1 select col1 from StaticTable;
end
2人のユーザー用にシステムをセットアップし、保存されたプロシージャInsert_Table1を設定した後
User1でストアドプロシージャを実行しようとすると、このエラーが発生します
メッセージ208、レベル16、状態1、プロシージャInsert_Table1、行6無効なオブジェクト名 'table1'。
しかし、クエリをuser1として個別に実行すると、問題なく実行されます。
ストアドプロシージャを実行している間、ストアドプロシージャは一時的にそのストアドプロシージャのスキーマ所有者の権限を取得します。
すでにuser1に割り当てられているロールへの権限を持つスキーマを作成しました。
Create Schema [StoredProcedures] AUTHORIZATION [ExecuteSprocsOnStoredProcsSchema]
何か不足していますか?機能させる方法はありますか?または、単一のストアドプロシージャを複数のスキーマで使用できる方法はありますか?.
おそらく動的SQLを使用できます。
CREATE PROCEDURE [StoredProcedures].[Insert_Table1]
AS
DECLARE @sql nvarchar(max)=N'
INSERT INTO table1 VALUES (NEWID());
INSERT INTO table1 SELECT col1 FROM StaticTable;
';
EXECUTE sys.sp_executesql @sql;
ただし、これはいくつかの理由で問題があることに注意してください。最も明白なものは次のとおりです。
私があなたが達成しようとしていることが可能であるとは信じていません。少なくとも、動的SQLの過度に複雑なレイヤーがなければ不可能です。
一意のログインとスキーマを作成する問題をすでに経験しているので、次のいずれかの方法を検討することをお勧めします。
個別のスキーマの概念を受け入れ、各スキーマにストアドプロシージャ(および関数?)を作成します。あなたは言及しました(今削除された重複した質問からの引用):
各スキーマのメンテナンスオーバーヘッドを回避するために、各スキーマで同じストアドプロシージャのセットを実行する必要があります。
しかし、どのようなメンテナンスのオーバーヘッドですか?スキーマごとに同じテーブルがすでにあるため、リリース/ロールアウトプロセスでは、テーブル/制約/トリガー/インデックスの変更をすべてのスキーマに適用する必要があるため、「コード」オブジェクトをミックスに追加するとどのような害がありますか(また、トリガーはテーブルごとに存在するため、すでに各スキーマにコピーされています。
分離としてのスキーマの使用から離れ、各クライアントごとにデータベースを作成します。これにより、すべてのオブジェクトを同一にすることができます。各スキーマではなく、各データベースにデプロイする必要があるだけです。しかし、一連のデータベース全体でリリース/ロールアウト/デプロイメントを行う必要性は、一連のスキーマ(現在のモデルですでに行う必要があるもの)全体でそれを行う必要性と何ら変わりはありません。