【问题标题】:How to collate sysname in sql server如何在sql server中整理sysname
【发布时间】:2015-06-09 16:30:52
【问题描述】:

我正在尝试运行查询以删除来自 Windows 的服务器登录并重新创建它们。我运行此查询以删除登录名,它工作正常

USE master
SELECT 
       'IF EXISTS (SELECT * FROM sys.server_principals WHERE name = ' + 
       '''' + [name] + '''' + ')' +
       ' BEGIN DROP LOGIN ' + QUOTENAME([name]) + ' END; ' + 
       'CREATE LOGIN ' + QUOTENAME([name]) + ' FROM WINDOWS; '
FROM sys.server_principals  
WHERE type_desc IN ('WINDOWS_GROUP' , 'WINDOWS_LOGIN')

但是下面的查询

USE master
SELECT 
       'ALTER LOGIN ' + QUOTENAME([name]) + ' WITH DEFAULT_DATABASE = ' + 
        spr.default_database_name
       + 'GRANT ' + spe.permission_name  + ' to ' + QUOTENAME([name])
       + CASE WHEN spr.default_database_name IS NOT NULL
            THEN ' WITH DEFAULT DATABASE = ' + spr.default_database_name
            ELSE 
            ''
        END
FROM sys.server_principals spr INNER JOIN 
     sys.server_permissions spe  ON spr.principal_id = spe.grantee_principal_id
WHERE spr.type_desc IN ('WINDOWS_GROUP', 'WINDOWS_LOGIN')

返回此错误

Cannot resolve collation conflict for column 1 in SELECT statement.

所以当我调查这个问题时,它来自sysname 列default_database_name 当我使用spr.default_database_name COLLATE Latin1_General_CI_AI 时,查询运行 我的三部分问题是:我遇到问题是因为一行还是因为列数据类型是sysname?。 COLLATE Latin1_General_CI_AI 是这种场景的正确语法吗? 当我运行这个查询时

SELECT name, description
FROM sys.fn_helpcollations()

结果显示了不同语言的许多排序规则。那么对于一个完全英文的数据库,我是如何得到这个错误的。

编辑: 我运行这两个查询来检查数据库和服务器的排序规则属性

SELECT DATABASEPROPERTYEX(N'master', N'Collation')
SELECT SERVERPROPERTY(N'Collation')

他们两个的结果都是

SQL_Latin1_General_CP1_CI_AS

【问题讨论】:

  • 我的猜测是您的数据库排序规则与服务器排序规则不同。 (这并不典型,但肯定也不少见。)如果您运行SELECT DATABASEPROPERTYEX(N'MyDatabaseName', N'Collation') 和SELECT SERVERPROPERTY(N'Collation'),您的结果是什么?
  • @DeadZone 感谢您的评论。我将更新我的答案以包含这些查询的结果。
  • 如果您运行sp_help [sys.server_principals]; 并查看default_database_name 列的排序规则,是否匹配?
  • 是的。它是 SQL_Latin1_General_CP1_CI_AS
  • 这似乎很奇怪...您说为了修复错误,您必须将default_database_name 列强行整理到Latin1_General_CI_AI。但这是一个重音不敏感排序规则,您的默认排序规则是重音敏感排序。这对我来说没有意义。您确定您列出的信息正确吗?

标签: sql-server sql-server-2008-r2


【解决方案1】:

为数据库和服务器实例引入默认排序规则可能会有所帮助,如下所示更改查询:

SELECT 
       'ALTER LOGIN ' + QUOTENAME([name]) + ' WITH DEFAULT_DATABASE = ' + 
        spr.default_database_name COLLATE database_default
       + 'GRANT ' + spe.permission_name  + ' to ' + QUOTENAME([name])
       + CASE WHEN spr.default_database_name IS NOT NULL
            THEN ' WITH DEFAULT DATABASE = ' + spr.default_database_name COLLATE database_default
            ELSE 
            ''
        END
FROM sys.server_principals spr INNER JOIN 
     sys.server_permissions spe  ON spr.principal_id = spe.grantee_principal_id
WHERE spr.type_desc IN ('WINDOWS_GROUP', 'WINDOWS_LOGIN')

【讨论】:

    【解决方案2】:

    看起来 MS 的某个人已将 sys.server_permissions.state_desc 上的排序规则修复为 Latin1_General_CI_AS_KS_WS

    我尝试了多个实例(SQL 2016)并发现了同样的问题。将“collat​​e database_default”设置为有效。

    【讨论】:

      【解决方案3】:

      您的问题的解决方案:为您 CONCAT 的两列指定排序规则

      USE master
      GO
      SELECT 
         'ALTER LOGIN ' + QUOTENAME([name]) COLLATE SQL_Latin1_General_CP1_CI_AS + 
      ' WITH DEFAULT_DATABASE = ' + 
          spr.default_database_name COLLATE SQL_Latin1_General_CP1_CI_AS
         + 'GRANT ' + spe.permission_name  + ' to ' + QUOTENAME([name])
         + CASE WHEN spr.default_database_name IS NOT NULL
              THEN ' WITH DEFAULT DATABASE = ' + spr.default_database_name
              ELSE 
              ''
          END
      FROM sys.server_principals spr INNER JOIN 
       sys.server_permissions spe  ON spr.principal_id = spe.grantee_principal_id
      WHERE spr.type_desc IN ('WINDOWS_GROUP', 'WINDOWS_LOGIN')
      

      【讨论】:

        猜你喜欢
        • 2019-02-16
        • 2011-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-15
        相关资源
        最近更新 更多