Mar*_*lli 2 xml sql-server collation permissions dynamic-sql
运行以下查询时,我收到以下错误消息:
无法解决 equal to 操作中“Latin1_General_CI_AS”和“Latin1_General_BIN”之间的排序冲突
此查询工作正常,基本上为我提供了在当前数据库中创建用户的脚本。
为了在当前服务器中的所有(或选择)数据库中运行查询,我通过动态 SQL 和 XML PATH 完成了它。
问题是,当我取消注释下面脚本的 XML 部分时,出现上面的错误。
我不是在所有服务器中都收到此错误。有些服务器工作正常,有些则陷入困境。
我希望此查询可以在所有服务器中运行,而与服务器排序规则无关。
我怎样才能做到这一点?
DECLARE @sql NVARCHAR(MAX)
DECLARE @ParamDefinition NVARCHAR(MAX)
DECLARE @log NVARCHAR(MAX)
,@vCrlf CHAR(2);
SELECT @log = ''
,@vCrlf = CHAR(13)+CHAR(10);
SELECT @SQL = '
--==========================================
-- creating the users
--==========================================
select db = db_name(),
_login=[master].[sys].[server_principals].[name],
role_= null,
obj=null,
Permission= null,
[script]=
''CREATE USER [''
+ [sys].[database_principals].[name] + '']'' + '' FOR LOGIN ['' + [master].[sys].[server_principals].[name] + '']''
from [sys].[database_principals] INNER JOIN [master].[sys].[server_principals]
on [sys].[database_principals].[name]=[master].[sys].[server_principals].[name]
where [master].[sys].[server_principals].[type] in (''U'', ''G'', ''S'')
'
--SET @SQL = (
-- SELECT STUFF(
-- (SELECT N' ' + ' USE ' + QUOTENAME(name) +';' + @vCrlf + @SQL + @vCrlf
-- FROM sys.databases SD
-- --INNER JOIN @DBS D ON SD.NAME = D.DB
-- WHERE SD.STATE_DESC = 'ONLINE' -->Skips the database if it is not online
-- AND SD.COMPATIBILITY_LEVEL > 80
-- FOR XML PATH(''),TYPE)
-- .value('text()[1]','nvarchar(max)'),1,2,N'')
--)
EXECUTE MASTER.DBO.sp_executesql @SQL
Run Code Online (Sandbox Code Playgroud)
这是工作版本
DECLARE @sql NVARCHAR(MAX)
DECLARE @ParamDefinition NVARCHAR(MAX)
DECLARE @log NVARCHAR(MAX)
,@vCrlf CHAR(2);
SELECT @log = ''
,@vCrlf = CHAR(13)+CHAR(10);
SELECT @SQL = '
--==========================================
-- creating the users
--==========================================
select db = db_name(),
_login=[master].[sys].[server_principals].[name],
role_= null,
obj=null,
Permission= null,
[script]=
''CREATE USER [''
+ [sys].[database_principals].[name] + '']'' + '' FOR LOGIN ['' COLLATE Latin1_General_CI_AS + [master].[sys].[server_principals].[name] + '']''
from [sys].[database_principals] INNER JOIN [master].[sys].[server_principals]
on [sys].[database_principals].[name] COLLATE Latin1_General_CI_AS = [master].[sys].[server_principals].[name]
where [master].[sys].[server_principals].[type] in (''U'', ''G'', ''S'')
'
SET @SQL = (
SELECT STUFF(
(SELECT N' ' + ' USE ' + QUOTENAME(name) +';' + @vCrlf + @SQL + @vCrlf
FROM sys.databases SD
--INNER JOIN @DBS D ON SD.NAME = D.DB
WHERE SD.STATE_DESC = 'ONLINE' -->Skips the database if it is not online
AND SD.COMPATIBILITY_LEVEL > 80
FOR XML PATH(''),TYPE)
.value('text()[1]','nvarchar(max)'),1,2,N'')
)
EXECUTE MASTER.DBO.sp_executesql @SQL
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用COLLATE DATABASE_DEFAULT
vs 明确指定排序规则。
DECLARE @sql NVARCHAR(MAX)
DECLARE @ParamDefinition NVARCHAR(MAX)
DECLARE @log NVARCHAR(MAX)
,@vCrlf CHAR(2);
SELECT @log = ''
,@vCrlf = CHAR(13)+CHAR(10);
SELECT @sql = '
--==========================================
-- creating the users
--==========================================
select db = db_name(),
_login=[master].[sys].[server_principals].[name],
role_= null,
obj=null,
Permission= null,
[script]=
''CREATE USER [''
+ [sys].[database_principals].[name] collate database_default + '']'' + '' FOR LOGIN ['' + [master].[sys].[server_principals].[name] collate database_default + '']''
from [sys].[database_principals] INNER JOIN [master].[sys].[server_principals]
on [sys].[database_principals].[name] collate database_default =[master].[sys].[server_principals].[name] collate database_default
where [master].[sys].[server_principals].[type] in (''U'', ''G'', ''S'')
'
SET @sql = (
SELECT STUFF(
(SELECT N' ' + ' USE ' + QUOTENAME(name) +';' + @vCrlf + @sql + @vCrlf
FROM sys.databases SD
--INNER JOIN @DBS D ON SD.NAME = D.DB
WHERE SD.state_desc = 'ONLINE' -->Skips the database if it is not online
AND SD.compatibility_level > 80
FOR XML PATH(''),TYPE)
.value('text()[1]','nvarchar(max)'),1,2,N'')
)
--EXECUTE master.dbo.sp_executesql @SQL
print @sql
Run Code Online (Sandbox Code Playgroud)
以上查询将产生以下打印语句:
select db = db_name(),
_login=[master].[sys].[server_principals].[name],
role_= null,
obj=null,
Permission= null,
[script]=
'CREATE USER ['
+ [sys].[database_principals].[name] collate database_default + ']' + ' FOR LOGIN [' + [master].[sys].[server_principals].[name] collate database_default + ']'
from [sys].[database_principals] INNER JOIN [master].[sys].[server_principals]
on [sys].[database_principals].[name] collate database_default =[master].[sys].[server_principals].[name] collate database_default
where [master].[sys].[server_principals].[type] in ('U', 'G', 'S')
Run Code Online (Sandbox Code Playgroud)