web-dev-qa-db-ja.com

単一のストアドプロシージャを使用して、実行中のユーザーに基づいて異なるスキーマを操作できますか

同じテーブルセットを持つ数千のスキーマがあり、各ユーザーにはデフォルトのスキーマがあります。しかし、すべてのスキーマに単一のストアドプロシージャのコピーを作成したくありません。単一のストアドプロシージャがユーザー固有のスキーマのテーブルにアクセスできますか。

これをテストするためにテストプロジェクトを作成しましたが、テーブルが見つからないためエラーが発生しています

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]

何か不足していますか?機能させる方法はありますか?または、単一のストアドプロシージャを複数のスキーマで使用できる方法はありますか?.

3
mayur rathi

おそらく動的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;

ただし、これはいくつかの理由で問題があることに注意してください。最も明白なものは次のとおりです。

  • すべてのユーザーのスキーマ全体を複製している場合、データベースの設計に深刻な問題がある可能性があります。ユーザーに独自のスキーマを与える代わりに、テーブルへの権限を設計する必要があります(ユーザー列と行レベルのセキュリティを使用)。
  • 所有権の連鎖が解除されます(userは、ストアドプロシージャから権限を継承するのではなく、ベーステーブルへのアクセス許可が必要になります)。
  • ストアドプロシージャがSQLステートメントに入るパラメーターを受け入れる場合(できればパラメーター化を使用)、SQLインジェクションを管理する必要があります。
  • 動的SQLには、パラメーター化とパフォーマンスに関して他のいくつかの影響があります。これは、より大きなOLTPスタイルの負荷を処理する場合に注意する必要があります。
3

私があなたが達成しようとしていることが可能であるとは信じていません。少なくとも、動的SQLの過度に複雑なレイヤーがなければ不可能です。

一意のログインとスキーマを作成する問題をすでに経験しているので、次のいずれかの方法を検討することをお勧めします。

  1. 個別のスキーマの概念を受け入れ、各スキーマにストアドプロシージャ(および関数?)を作成します。あなたは言及しました(今削除された重複した質問からの引用):

    各スキーマのメンテナンスオーバーヘッドを回避するために、各スキーマで同じストアドプロシージャのセットを実行する必要があります。

    しかし、どのようなメンテナンスのオーバーヘッドですか?スキーマごとに同じテーブルがすでにあるため、リリース/ロールアウトプロセスでは、テーブル/制約/トリガー/インデックスの変更をすべてのスキーマに適用する必要があるため、「コード」オブジェクトをミックスに追加するとどのような害がありますか(また、トリガーはテーブルごとに存在するため、すでに各スキーマにコピーされています。

  2. 分離としてのスキーマの使用から離れ、各クライアントごとにデータベースを作成します。これにより、すべてのオブジェクトを同一にすることができます。各スキーマではなく、各データベースにデプロイする必要があるだけです。しかし、一連のデータベース全体でリリース/ロールアウト/デプロイメントを行う必要性は、一連のスキーマ(現在のモデルですでに行う必要があるもの)全体でそれを行う必要性と何ら変わりはありません。

3
Solomon Rutzky