【发布时间】:2018-05-07 02:33:07
【问题描述】:
环境:SQL SERVER 2016 我在 SQL 中使用 execute as user 函数来创建特定于会话的表,而不使用动态 SQL。当我将代码作为单个查询运行时,它的执行完全符合预期。工作代码是:
DECLARE @strSQL NVARCHAR(MAX)
, @strSession AS NVARCHAR(256)
SET @strSession = 'SESSION_ABCD'
SET @strSQL = 'CREATE SCHEMA ' + @strSession
PRINT (@strSQL)
EXEC (@strSQL)
SET @strSQL = 'CREATE LOGIN ' + @strSession + ' WITH PASSWORD = ''' + CAST(NEWID() AS NVARCHAR(36)) + ''' '
PRINT (@strSQL)
EXEC (@strSQL)
SET @strSQL = 'CREATE USER ' + @strSession
PRINT (@strSQL)
EXEC (@strSQL)
SET @strSQL = 'ALTER USER ' + @strSession + ' WITH DEFAULT_SCHEMA = ' + @strSession
PRINT (@strSQL)
EXEC (@strSQL)
SET @strSQL = 'GRANT ALTER ON SCHEMA::' + @strSession + ' TO ' + @strSession
PRINT (@strSQL)
EXEC (@strSQL)
SET @strSQL = 'GRANT CREATE TABLE TO ' + @strSession
PRINT (@strSQL)
EXEC (@strSQL)
SET @strSQL = 'GRANT SELECT,INSERT,UPDATE,DELETE TO ' + @strSession
PRINT (@strSQL)
EXEC (@strSQL)
EXECUTE AS USER = 'SESSION_ABCD'
-- Create table without including default schema - OK
-- Creates table SESSION_ABCD.Test as expected
CREATE TABLE Test (MyValue INT)
-- Select from table including schema name - OK
SELECT *
FROM SESSION_ABCD.Test
-- Select from table excluding schema name - Works outside of stored procedure
SELECT *
FROM Test
REVERT
但是,如果我在存储的 [过程中运行相同的代码,我会得到意想不到的结果。代码如下:
CREATE PROC dbo.SetupUser
AS
BEGIN
DECLARE @strSession AS NVARCHAR(256)
SET @strSession = 'SESSION_ABCD'
DECLARE @strSQL NVARCHAR(MAX)
SET @strSQL = 'CREATE SCHEMA ' + @strSession
PRINT (@strSQL)
EXEC (@strSQL)
SET @strSQL = 'CREATE LOGIN ' + @strSession + ' WITH PASSWORD = ''' + CAST(NEWID() AS NVARCHAR(36)) + ''' '
PRINT (@strSQL)
EXEC (@strSQL)
SET @strSQL = 'CREATE USER ' + @strSession
PRINT (@strSQL)
EXEC (@strSQL)
SET @strSQL = 'ALTER USER ' + @strSession + ' WITH DEFAULT_SCHEMA = ' + @strSession
PRINT (@strSQL)
EXEC (@strSQL)
SET @strSQL = 'GRANT ALTER ON SCHEMA::' + @strSession + ' TO ' + @strSession
PRINT (@strSQL)
EXEC (@strSQL)
SET @strSQL = 'GRANT CREATE TABLE TO ' + @strSession
PRINT (@strSQL)
EXEC (@strSQL)
SET @strSQL = 'GRANT SELECT,INSERT,UPDATE,DELETE TO ' + @strSession
PRINT (@strSQL)
EXEC (@strSQL)
END
GO
CREATE PROC dbo.SetupTable
AS
BEGIN
EXECUTE AS USER = 'SESSION_ABCD'
-- Create table without including default schema - OK
-- Creates table SESSION_ABCD.Test as expected
CREATE TABLE Test (MyValue INT)
-- Select from table including schema name - OK
SELECT *
FROM SESSION_ABCD.Test
-- Select from table excluding schema name - Fails
-- Expecting same result as above
PRINT SCHEMA_NAME()
SELECT *
FROM Test
REVERT
END
GO
EXEC dbo.SetupUser
EXEC dbo.SetupTable
当我执行上面的脚本时,用户/会话/等配置正确。 (请注意,您需要从系统中删除它们才能再次运行它们。)在 SetupTable 过程中,create table 命令针对默认模式执行,但是 select 命令需要使用模式名称进行限定。虽然我可以使用动态 SQL 构建查询以插入架构名称,但这个项目完全是围绕删除旧的动态 sql 代码。
老实说,这不是我以前使用过的方法,但似乎是解决另一个问题的最建议的解决方案。我希望我缺少一些基本的东西,但现在我完全被难住了。
非常感谢。
【问题讨论】:
标签: sql-server stored-procedures permissions schema sql-server-2016