sys.databases에서 일부 열의 데이터 정렬은 무엇입니까?


21

2005 년에서 2012 년까지 다양한 버전의 SQL Server에 UNPIVOT포함 된 다양한 열 에서 실행하려고합니다 sys.databases.

UNPIVOT다음 오류 메시지와 함께 실패 :

메시지 8167, 수준 16, 상태 1, 줄 48

"CompatibilityLevel"열 유형이 UNPIVOT 목록에 지정된 다른 열 유형과 충돌합니다.

T-SQL :

DECLARE @dbname SYSNAME;
SET @dbname = DB_NAME();

SELECT [Database]            = unpvt.DatabaseName
    , [Configuration Item]   = unpvt.OptionName
    , [Configuration Value]  = unpvt.OptionValue
FROM (
    SELECT 
        DatabaseName = name 
        , RecoveryModel                 = CONVERT(VARCHAR(50), d.recovery_model_desc)
        , CompatibilityLevel            = CONVERT(VARCHAR(50), CASE d.[compatibility_level] WHEN 70 THEN 'SQL Server 7' WHEN 80 THEN 'SQL Server 2000' WHEN 90 THEN 'SQL Server 2005' WHEN 100 THEN 'SQL Server 2008' WHEN 110 THEN 'SQL Server 2012' WHEN 120 THEN 'SQL Server 2014' ELSE 'UNKNOWN' END)
        , AutoClose                     = CONVERT(VARCHAR(50), CASE d.is_auto_close_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , AutoCreateStatistics          = CONVERT(VARCHAR(50), CASE d.is_auto_create_stats_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , AutoShrink                    = CONVERT(VARCHAR(50), CASE d.is_auto_shrink_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , AutoUpdateStatistics          = CONVERT(VARCHAR(50), CASE d.is_auto_update_stats_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , AutoUpdateStatisticsAsynch    = CONVERT(VARCHAR(50), CASE d.is_auto_update_stats_async_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , CloseCursorOnCommit           = CONVERT(VARCHAR(50), CASE d.is_cursor_close_on_commit_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , DefaultCursor                 = CONVERT(VARCHAR(50), CASE d.is_local_cursor_default WHEN 1 THEN 'LOCAL' ELSE 'GLOBAL' END)
        , ANSINULL_Default              = CONVERT(VARCHAR(50), CASE d.is_ansi_null_default_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ANSINULLS_Enabled             = CONVERT(VARCHAR(50), CASE d.is_ansi_nulls_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ANSIPadding_Enabled           = CONVERT(VARCHAR(50), CASE d.is_ansi_padding_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ANSIWarnings_Enabled          = CONVERT(VARCHAR(50), CASE d.is_ansi_warnings_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ArithmeticAbort_Enabled       = CONVERT(VARCHAR(50), CASE d.is_arithabort_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ConcatNullYieldsNull          = CONVERT(VARCHAR(50), CASE d.is_concat_null_yields_null_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , CrossDBOwnerChain             = CONVERT(VARCHAR(50), CASE d.is_db_chaining_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , DateCorrelationOptimized      = CONVERT(VARCHAR(50), CASE d.is_date_correlation_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , NumericRoundAbort             = CONVERT(VARCHAR(50), CASE d.is_numeric_roundabort_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , [Parameterization]            = CONVERT(VARCHAR(50), CASE d.is_parameterization_forced WHEN 0 THEN 'SIMPLE' ELSE 'FORCED' END)
        , QuotedIdentifiers_Enabled     = CONVERT(VARCHAR(50), CASE d.is_quoted_identifier_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , RecursiveTriggers_Enabled     = CONVERT(VARCHAR(50), CASE d.is_recursive_triggers_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , [TrustWorthy]                 = CONVERT(VARCHAR(50), CASE d.is_trustworthy_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , VARDECIMAL_Storage            = CONVERT(VARCHAR(50), 'TRUE')
        , PageVerify                    = CONVERT(VARCHAR(50), page_verify_option_desc  )
        , BrokerEnabled                 = CONVERT(VARCHAR(50), CASE d.is_broker_enabled WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , DatabaseReadOnly              = CONVERT(VARCHAR(50), CASE d.is_read_only WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , EncryptionEnabled             = CONVERT(VARCHAR(50), CASE d.is_encrypted WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , RestrictedAccess              = CONVERT(VARCHAR(50), user_access_desc)
        , Collation                     = CONVERT(VARCHAR(50), d.collation_name)
    FROM sys.databases d
    WHERE name = @dbname
        OR @dbname IS NULL
    ) src
UNPIVOT
(
    OptionValue FOR OptionName IN
    (
        RecoveryModel
        , CompatibilityLevel
        , AutoClose
        , AutoCreateStatistics 
        , AutoShrink 
        , AutoUpdateStatistics 
        , AutoUpdateStatisticsAsynch 
        , CloseCursorOnCommit 
        , DefaultCursor 
        , ANSINULL_Default 
        , ANSINULLS_Enabled 
        , ANSIPadding_Enabled 
        , ANSIWarnings_Enabled 
        , ArithmeticAbort_Enabled 
        , ConcatNullYieldsNull 
        , CrossDBOwnerChain 
        , DateCorrelationOptimized 
        , NumericRoundAbort 
        , [Parameterization] 
        , QuotedIdentifiers_Enabled 
        , RecursiveTriggers_Enabled 
        , [TrustWorthy] 
        , VARDECIMAL_Storage 
        , PageVerify 
        , BrokerEnabled 
        , DatabaseReadOnly 
        , EncryptionEnabled 
        , RestrictedAccess 
        , Collation
    )
) AS unpvt;

이것은 다음과 유사하게 주어진 데이터베이스에 대한 형식이 지정된 데이터베이스 옵션 목록을 제공하도록 설계되었습니다.

+----------+----------------------------+----------------------------+
| Database | Configuration Item         | Value in Use               |
+----------+----------------------------+----------------------------+
| master   | RecoveryModel              | SIMPLE                     |
| master   | CompatibilityLevel         | SQL Server 2008            |
| master   | AutoClose                  | FALSE                      |
| master   | AutoCreateStatistics       | TRUE                       |
| master   | AutoShrink                 | FALSE                      |
| master   | AutoUpdateStatistics       | TRUE                       |
| master   | AutoUpdateStatisticsAsynch | FALSE                      |
| master   | CloseCursorOnCommit        | FALSE                      |
| master   | DefaultCursor              | GLOBAL                     |
| master   | ANSINULL_Default           | FALSE                      |
| master   | ANSINULLS_Enabled          | FALSE                      |
| master   | ANSIPadding_Enabled        | FALSE                      |
| master   | ANSIWarnings_Enabled       | FALSE                      |
| master   | ArithmeticAbort_Enabled    | FALSE                      |
| master   | ConcatNullYieldsNull       | FALSE                      |
| master   | CrossDBOwnerChain          | TRUE                       |
| master   | DateCorrelationOptimized   | FALSE                      |
| master   | NumericRoundAbort          | FALSE                      |
| master   | Parameterization           | SIMPLE                     |
| master   | QuotedIdentifiers_Enabled  | FALSE                      |
| master   | RecursiveTriggers_Enabled  | FALSE                      |
| master   | TrustWorthy                | TRUE                       |
| master   | VARDECIMAL_Storage         | TRUE                       |
| master   | PageVerify                 | CHECKSUM                   |
| master   | BrokerEnabled              | FALSE                      |
| master   | DatabaseReadOnly           | FALSE                      |
| master   | EncryptionEnabled          | FALSE                      |
| master   | RestrictedAccess           | MULTI_USER                 |
| master   | Collation                  | Latin1_General_CI_AS_KS_WS |
+----------+----------------------------+----------------------------+

Latin1_General_CI_AS_KS_WS데이터 정렬 을 사용하여 서버에서 이것을 실행 하면 명령문이 성공합니다. 특정 필드에 COLLATE절이 있도록 T-SQL을 수정하면 다른 데이터 정렬이있는 서버에서 실행됩니다.

데이터 정렬이 아닌 서버에서 작동하는 코드 Latin1_General_CI_AS_KS_WS는 다음과 같습니다.

DECLARE @dbname SYSNAME;
SET @dbname = DB_NAME();

SELECT [Database]            = unpvt.DatabaseName
    , [Configuration Item]   = unpvt.OptionName
    , [Configuration Value]  = unpvt.OptionValue
FROM (
    SELECT 
        DatabaseName = name 
        , RecoveryModel                 = CONVERT(VARCHAR(50), d.recovery_model_desc) COLLATE SQL_Latin1_General_CP1_CI_AS
        , CompatibilityLevel            = CONVERT(VARCHAR(50), CASE d.[compatibility_level] WHEN 70 THEN 'SQL Server 7' WHEN 80 THEN 'SQL Server 2000' WHEN 90 THEN 'SQL Server 2005' WHEN 100 THEN 'SQL Server 2008' WHEN 110 THEN 'SQL Server 2012' WHEN 120 THEN 'SQL Server 2014' ELSE 'UNKNOWN' END) 
        , AutoClose                     = CONVERT(VARCHAR(50), CASE d.is_auto_close_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , AutoCreateStatistics          = CONVERT(VARCHAR(50), CASE d.is_auto_create_stats_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , AutoShrink                    = CONVERT(VARCHAR(50), CASE d.is_auto_shrink_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , AutoUpdateStatistics          = CONVERT(VARCHAR(50), CASE d.is_auto_update_stats_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , AutoUpdateStatisticsAsynch    = CONVERT(VARCHAR(50), CASE d.is_auto_update_stats_async_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , CloseCursorOnCommit           = CONVERT(VARCHAR(50), CASE d.is_cursor_close_on_commit_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , DefaultCursor                 = CONVERT(VARCHAR(50), CASE d.is_local_cursor_default WHEN 1 THEN 'LOCAL' ELSE 'GLOBAL' END)
        , ANSINULL_Default              = CONVERT(VARCHAR(50), CASE d.is_ansi_null_default_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ANSINULLS_Enabled             = CONVERT(VARCHAR(50), CASE d.is_ansi_nulls_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ANSIPadding_Enabled           = CONVERT(VARCHAR(50), CASE d.is_ansi_padding_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ANSIWarnings_Enabled          = CONVERT(VARCHAR(50), CASE d.is_ansi_warnings_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ArithmeticAbort_Enabled       = CONVERT(VARCHAR(50), CASE d.is_arithabort_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ConcatNullYieldsNull          = CONVERT(VARCHAR(50), CASE d.is_concat_null_yields_null_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , CrossDBOwnerChain             = CONVERT(VARCHAR(50), CASE d.is_db_chaining_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , DateCorrelationOptimized      = CONVERT(VARCHAR(50), CASE d.is_date_correlation_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , NumericRoundAbort             = CONVERT(VARCHAR(50), CASE d.is_numeric_roundabort_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , [Parameterization]            = CONVERT(VARCHAR(50), CASE d.is_parameterization_forced WHEN 0 THEN 'SIMPLE' ELSE 'FORCED' END)
        , QuotedIdentifiers_Enabled     = CONVERT(VARCHAR(50), CASE d.is_quoted_identifier_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , RecursiveTriggers_Enabled     = CONVERT(VARCHAR(50), CASE d.is_recursive_triggers_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , [TrustWorthy]                 = CONVERT(VARCHAR(50), CASE d.is_trustworthy_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , VARDECIMAL_Storage            = CONVERT(VARCHAR(50), 'TRUE')
        , PageVerify                    = CONVERT(VARCHAR(50), page_verify_option_desc  ) COLLATE SQL_Latin1_General_CP1_CI_AS
        , BrokerEnabled                 = CONVERT(VARCHAR(50), CASE d.is_broker_enabled WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , DatabaseReadOnly              = CONVERT(VARCHAR(50), CASE d.is_read_only WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , EncryptionEnabled             = CONVERT(VARCHAR(50), CASE d.is_encrypted WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , RestrictedAccess              = CONVERT(VARCHAR(50), user_access_desc) COLLATE SQL_Latin1_General_CP1_CI_AS
        , Collation                     = CONVERT(VARCHAR(50), d.collation_name)
    FROM sys.databases d
    WHERE name = @dbname
        OR @dbname IS NULL
    ) src
UNPIVOT
(
    OptionValue FOR OptionName IN
    (
        RecoveryModel
        , CompatibilityLevel
        , AutoClose
        , AutoCreateStatistics 
        , AutoShrink 
        , AutoUpdateStatistics 
        , AutoUpdateStatisticsAsynch 
        , CloseCursorOnCommit 
        , DefaultCursor 
        , ANSINULL_Default 
        , ANSINULLS_Enabled 
        , ANSIPadding_Enabled 
        , ANSIWarnings_Enabled 
        , ArithmeticAbort_Enabled 
        , ConcatNullYieldsNull 
        , CrossDBOwnerChain 
        , DateCorrelationOptimized 
        , NumericRoundAbort 
        , [Parameterization] 
        , QuotedIdentifiers_Enabled 
        , RecursiveTriggers_Enabled 
        , [TrustWorthy] 
        , VARDECIMAL_Storage 
        , PageVerify 
        , BrokerEnabled 
        , DatabaseReadOnly 
        , EncryptionEnabled 
        , RestrictedAccess 
        , Collation
    )
) AS unpvt;

관찰 된 동작은 다음 필드가 서버 데이터 정렬 또는 데이터베이스 데이터 정렬을 관찰하지 않는 것입니다. 그들은 항상Latin1_General_CI_AS_KS_WS 데이터 정렬로 표시됩니다 .

SQL Server 2012에서는 sys.sp_describe_first_result_set특정 쿼리에서 반환 된 열에 대한 메타 데이터를 쉽게 얻을 수 있습니다 . 데이터 정렬 불일치를 결정하기 위해 다음을 사용했습니다.

DECLARE @cmd NVARCHAR(MAX);

SET @cmd = '
SELECT 
    DatabaseName                    = CONVERT(VARCHAR(50), d.name)
    , RecoveryModel                 = CONVERT(VARCHAR(50), d.recovery_model_desc) 
    , Collation                     = CONVERT(VARCHAR(50), d.collation_name)
FROM sys.databases d
WHERE name = DB_NAME();
';

EXEC sp_describe_first_result_set @command = @cmd;

결과 :

여기에 이미지 설명을 입력하십시오

이러한 열의 데이터 정렬이 정적으로 설정되는 이유는 무엇입니까?

답변:


17

Microsoft의 공식 단어 :

미리 정의 된 문자열 (유형, 시스템 설명 및 상수 등)이 포함 된 일부 열은 항상 특정 데이터 정렬로 고정됩니다 Latin1_General_CI_AS_KS_WS. 이것은 인스턴스 / 데이터베이스 데이터 정렬과 관계가 없습니다. 그 이유는 이것이 시스템 메타 데이터 (사용자 메타 데이터가 아님)이며 기본적으로 이러한 문자열은 대소 문자를 구분하지 않는 것으로 취급됩니다 (키워드와 같이 항상 라틴어).

개체 이름, 열 이름, 인덱스 이름, 로그인 이름 등과 같은 사용자 메타 데이터가 포함 된 시스템 테이블의 다른 열은 인스턴스 또는 데이터베이스 데이터 정렬을 사용합니다. 인스턴스 데이터 정렬시 SQL Server 설치시 및 데이터베이스 데이터 정렬시 데이터베이스 생성시 열이 적절한 데이터 정렬로 정렬됩니다.

당신은 물었다 (강조 광산) :

이러한 열의 데이터 정렬이 정적으로 설정되는 이유무엇 입니까?

일부 열이 정적으로 설정되는 이유는 쿼리가 올바르게 작동하기 위해 서버 또는 데이터베이스 데이터 정렬 (더 중요한 것은 CaSe SenSiTIviTy)에 대해 걱정할 필요가 없기 때문입니다. 이 쿼리는 데이터 정렬에 관계없이 항상 작동합니다.

SELECT * FROM sys.databases WHERE state_desc = N'ONLine';

서버 데이터 정렬이 대소 문자를 구분하는 경우 위 쿼리는 다음과 같이 0 개의 행을 반환합니다.

  SELECT * FROM sys.databases 
  WHERE state_desc COLLATE Albanian_BIN = N'ONLine';

예를 들어 SQL_Estonian_CP1257_CS_AS데이터 정렬 을 사용하여 SQL Server 인스턴스를 설치하는 경우 다음을 실행하십시오.

SELECT name, collation_name 
FROM master.sys.all_columns
WHERE collation_name IS NOT NULL
AND [object_id] = OBJECT_ID(N'sys.databases');

다음 결과 (또는 SQL Server 버전에 따라 비슷한 결과)가 표시됩니다.

name                            SQL_Estonian_CP1257_CS_AS
collation_name                  SQL_Estonian_CP1257_CS_AS
user_access_desc                Latin1_General_CI_AS_KS_WS
state_desc                      Latin1_General_CI_AS_KS_WS
snapshot_isolation_state_desc   Latin1_General_CI_AS_KS_WS
recovery_model_desc             Latin1_General_CI_AS_KS_WS
page_verify_option_desc         Latin1_General_CI_AS_KS_WS
log_reuse_wait_desc             Latin1_General_CI_AS_KS_WS
default_language_name           SQL_Estonian_CP1257_CS_AS
default_fulltext_language_name  SQL_Estonian_CP1257_CS_AS
containment_desc                Latin1_General_CI_AS_KS_WS
delayed_durability_desc         SQL_Estonian_CP1257_CS_AS

이제 마스터 데이터베이스에서 서버 데이터 정렬을 상속하지 않고 데이터베이스 데이터 정렬을 상속하는 메타 데이터보기를 보여줍니다.

CREATE DATABASE server_collation;
GO
CREATE DATABASE albanian COLLATE Albanian_BIN;
GO
CREATE DATABASE hungarian COLLATE Hungarian_Technical_100_CS_AI;
GO

SELECT name, collation_name 
  FROM server_collation.sys.all_columns 
  WHERE collation_name IS NOT NULL 
  AND object_id = -391; -- sys.columns

SELECT name, collation_name 
  FROM albanian.sys.all_columns 
  WHERE collation_name IS NOT NULL 
  AND object_id = -391; -- sys.columns

SELECT name, collation_name 
  FROM hungarian.sys.all_columns 
  WHERE collation_name IS NOT NULL 
  AND object_id = -391; -- sys.columns

결과 :

server_collation
----------------
name                                 SQL_Estonian_CP1257_CS_AS
collation_name                       SQL_Estonian_CP1257_CS_AS
generated_always_type_desc           Latin1_General_CI_AS_KS_WS
encryption_type_desc                 Latin1_General_CI_AS_KS_WS
encryption_algorithm_name            Latin1_General_CI_AS_KS_WS
column_encryption_key_database_name  SQL_Estonian_CP1257_CS_AS


albanian
----------------
name                                 Albanian_BIN
collation_name                       Albanian_BIN
generated_always_type_desc           Latin1_General_CI_AS_KS_WS
encryption_type_desc                 Latin1_General_CI_AS_KS_WS
encryption_algorithm_name            Latin1_General_CI_AS_KS_WS
column_encryption_key_database_name  Albanian_BIN


hungarian
----------------
name                                 Hungarian_Technical_100_CS_AI
collation_name                       Hungarian_Technical_100_CS_AI
generated_always_type_desc           Latin1_General_CI_AS_KS_WS
encryption_type_desc                 Latin1_General_CI_AS_KS_WS
encryption_algorithm_name            Latin1_General_CI_AS_KS_WS
column_encryption_key_database_name  Hungarian_Technical_100_CS_AI

따라서이 경우 여러 열이 데이터베이스 데이터 정렬을 상속받는 반면 다른 열은이 "일반적인"Latin1 데이터 정렬로 고정되어있어 위에서 설명한대로 대 / 소문자 구분 문제로부터 특정 이름과 속성을 격리하는 데 사용됩니다.

UNION예 를 들어을 수행하려고하면

SELECT name FROM albanian.sys.columns
UNION ALL
SELECT name FROM server_collation.sys.columns;

이 오류가 발생합니다 :

메시지 451, 수준 16, 상태 1
SELECT 문 열 1에서 발생하는 UNION ALL 연산자의 "Albanian_BIN"과 "SQL_Estonian_CP1257_CS_AS"간의 데이터 정렬 충돌을 해결할 수 없습니다.

마찬가지로 PIVOT또는 을 수행하려고 UNPIVOT하면 규칙이 더 엄격 해지지 만 (출력 유형은 단순히 호환되는 것이 아니라 정확하게 일치해야 함 ) 오류 메시지는 훨씬 덜 유용하며 오도의 소지가 있습니다.

메시지 8167, 수준 16, 상태 1
열 이름 열의 유형이 UNPIVOT 목록에 지정된 다른 열 유형과 충돌합니다.

COLLATE쿼리에서 명시 적 절을 사용하여 이러한 오류를 해결 해야합니다. 예를 들어 위의 조합은 다음과 같습니다.

SELECT name COLLATE Latin1_General_CI_AS_KS_WS
  FROM albanian.sys.columns
UNION ALL
SELECT name COLLATE Latin1_General_CI_AS_KS_WS
  FROM server_collation.sys.columns;

데이터 정렬이 강제되었지만 동일한 문자 표현이 포함되어 있지 않거나 정렬이 사용되고 강제 정렬이 소스와 다른 정렬 순서를 사용하는 경우 문제가 발생할 수있는 유일한 시간은 혼란스러운 결과를 얻는 것입니다.


7

데이터 정렬 우선 순위에 대한 배경

시스템 카탈로그 뷰에서 다양한 필드의 데이터 정렬과 관련하여보고있는 동작은 각 필드가 정의 된 방식과 데이터 정렬 우선 순위입니다.

를 볼 때 sys.databases테이블이 아님을 명심해야합니다. 과거에 (SQL Server 2000에서 끝나는 것 같음) 이들은 시스템 카탈로그 테이블 이었지만 이제는 시스템 카탈로그 입니다. 따라서 정보의 소스가 반드시 현재 데이터베이스 컨텍스트 (또는 지정된 데이터베이스의 컨텍스트 (예 :master.sys.databases ) .

와 관련하여 특히 sys.databases일부 필드는 [master]데이터베이스 에서 가져옵니다 (인스턴스의 기본 데이터 정렬 (예 : 서버 수준 데이터 정렬)를 기반으로 한 데이터 정렬로 생성됨). 일부 필드는 표현식 (예 : CASE명령문)이며 일부는 "숨겨진"소스에서 : [mssqlsystemresource]데이터베이스 그리고 [mssqlsystemresource]데이터베이스의 데이터 정렬은 다음과 같습니다.Latin1_General_CI_AS_KS_WS .

name필드는의 name필드에서 제공 master.sys.sysdbreg됩니다. 따라서이 필드는 항상[master] 데이터베이스 하며 이는 서버의 데이터 정렬과 다시 일치합니다.

하지만,에서 다음 필드 sys.databases로부터 온 [name]분야 [mssqlsystemresource].[sys].[syspalvalues]:

  • user_access_desc
  • snapshot_isolation_state_desc
  • recovery_model_desc
  • page_verify_option_desc
  • log_reuse_wait_desc
  • containsment_desc

해당 필드의 데이터 정렬은 항상이어야합니다 Latin1_General_CI_AS_KS_WS.

collation_name필드는, 그러나, 다음과 같은 표현에서 유래 :

CONVERT(nvarchar(128),
        CASE
            WHEN serverproperty('EngineEdition')=5
                   AND [master].[sys].[sysdbreg].[id] as [d].[id]=(1)
              THEN serverproperty('collation')
            ELSE collationpropertyfromid(
                           CONVERT(int,
                            isnull([master].[sys].[sysobjvalues].[value] as [coll].[value],
                                   CONVERT_IMPLICIT(sql_variant,DBPROP.[cid],0)
                                ),
                         0),'name')
         END,
        0)

곳이다 정렬 우선 순위가 와서 시작 여기에 출력을위한 두 옵션은 시스템 기능은 다음과 같습니다. serverproperty()collationpropertyfromid(). 이 식의 데이터 정렬은 "강제 기본값"으로 간주됩니다.

Transact-SQL 문자열 변수, 매개 변수, 리터럴 또는 카탈로그 내장 함수의 출력 또는 문자열 입력을받지 않고 문자열 출력을 생성하는 내장 함수

오브젝트가 사용자 정의 함수, 스토어드 프로 시저 또는 트리거에 선언 된 경우, 오브젝트에는 함수, 스토어드 프로 시저 또는 트리거가 작성된 데이터베이스의 기본 데이터 정렬이 지정됩니다. 개체가 배치로 선언 된 경우 개체에는 연결을 위해 현재 데이터베이스의 기본 데이터 정렬이 할당됩니다.

두 번째 단락 sys.databases에 비추어 볼 때 master데이터베이스에 존재하는 뷰 이기 때문에 master현재 데이터베이스가 아닌 데이터베이스 의 데이터 정렬을 수행 합니다.

state_desc필드는 또한 표현식입니다.

CASE
   WHEN serverproperty('EngineEdition')=5
       AND [Expr1081]=(1)
       THEN N'RESTORING'
   ELSE
      CASE
         WHEN serverproperty('EngineEdition')=5
            AND CONVERT(bit,
                        [master].[sys].[sysdbreg].[status] as [d].[status]&(128),
                        0)=(1)
          THEN N'COPYING'
         ELSE
            CASE
               WHEN serverproperty('EngineEdition')=5
                  AND CONVERT(bit,
                              [master].[sys].[sysdbreg].[status] as [d].[status]&(256),
                              0)=(1)
                 THEN N'SUSPECT'
            ELSE [mssqlsystemresource].[sys].[syspalvalues].[name] as [st].[name]
            END
         END
       END

그러나이 식의 데이터 정렬은 Latin1_General_CI_AS_KS_WS입니다. 왜? 글쎄요,이 표현에는 새로운 것이 소개되어 있습니다 : [mssqlsystemresource].[sys].[syspalvalues].[name]마지막 ELSE절 에서 실제 필드에 대한 참조 . 열 참조는 "암시 적"으로 간주됩니다.

열 참조 표현식의 데이터 정렬은 테이블 또는 뷰의 열에 대해 정의 된 데이터 정렬에서 가져옵니다.

물론 이것은 흥미로운 질문을 제기합니다.이식 CASE이 평가 방법에 따라 다른 데이터 정렬을 반환 할 수 있습니까? 리터럴은이 개체가 정의 된 데이터베이스의 데이터 정렬에 있지만 ELSE조건은 원래 데이터 정렬을 유지해야하는 필드 값을 반환합니다. 다행히도 sys.dm_exec_describe_first_result_set 동적 관리 기능을 사용하여 테스트를 시뮬레이션 할 수 있습니다 .

-- Force ELSE condition
SELECT system_type_name, max_length, collation_name
FROM sys.dm_exec_describe_first_result_set(N'
DECLARE @A INT;
SET @A = -1;
SELECT CASE WHEN @A = 100 THEN N''All About the Benjamins''
            ELSE [name]
       END AS [Stuff]
FROM msdb.dbo.sysjobs
', NULL, NULL) rs

-- Force WHEN condition
SELECT system_type_name, max_length, collation_name
FROM sys.dm_exec_describe_first_result_set(N'
DECLARE @A INT;
SET @A = 100;
SELECT CASE WHEN @A = 100 THEN N''All About the Benjamins''
            ELSE [name]
       END AS [Stuff]
FROM msdb.dbo.sysjobs
', NULL, NULL) rs

-- Control test
SELECT system_type_name, max_length, collation_name
FROM sys.dm_exec_describe_first_result_set(N'
DECLARE @A INT;
SET @A = 100;
SELECT CASE WHEN @A = 100 THEN N''All About the Benjamins''
            ELSE N''Whazzup, yo?!?!?''
       END AS [Stuff]
', NULL, NULL) rs

데이터 정렬은 SQL_Latin1_General_CP1_CI_AS있지만 데이터 정렬은 데이터베이스에서 실행 되는 인스턴스에서 다음을 반환합니다 Japanese_Unicode_CI_AS.

system_type_name    max_length    collation_name
----------------    ----------    --------------
nvarchar(128)       256           SQL_Latin1_General_CP1_CI_AS
nvarchar(128)       256           SQL_Latin1_General_CP1_CI_AS
nvarchar(23)         46           Japanese_Unicode_CI_AS

여기에 우리가 볼 수 있다는 점에서 필드를 참조하는 두 쿼리 [msdb]의 정렬에 걸릴[msdb] 데이터베이스 (시스템 DB 인 서버 데이터 정렬에 의해 결정됨)을 합니다.

원래 질문으로 돌아 가기

관찰 된 동작은 다음 필드가 서버 데이터 정렬 또는 데이터베이스 데이터 정렬을 관찰하지 않는 것입니다. 그들은 항상Latin1_General_CI_AS_KS_WS 데이터 정렬로 표시됩니다 .

관찰 결과가 정확합니다. 해당 필드 Latin1_General_CI_AS_KS_WS는 서버 데이터 정렬 또는 데이터베이스 데이터 정렬에 관계없이 항상 데이터 정렬을가집니다. 그리고 그 이유는 데이터 정렬 우선 순위입니다. 이러한 필드는 [mssqlsystemresource]데이터베이스 의 테이블에서 가져 오며, COLLATE우선 순위가 가장 높은 명시 적 절로 재정의되지 않는 한 해당 초기 데이터 정렬을 유지합니다 .

명시 적 = 표현식에서 COLLATE 절을 사용하여 명시 적으로 특정 데이터 정렬로 캐스트되는 표현식입니다.

명시 적이 암시 적보다 우선합니다. 암시 적은 강제 강제 기본값보다 우선합니다.
명시 적> 암시 적> 강제 기본값

그리고 관련 질문 :

이러한 열의 데이터 정렬이 정적으로 설정되는 이유는 무엇입니까?

그것들이 정적으로 설정되어 있지 않고 다른 필드가 어떻게 든 동적이지는 않습니다. 모든 시스템 카탈로그 뷰의 모든 필드는 동일한 콜 레이션 우선 순위 규칙에서 작동합니다. 이들이 다른 필드보다 "정적"인 것처럼 보이는 이유는 (즉, 다른 기본 데이터 정렬을 사용하여 SQL Server를 설치하더라도 기본 데이터 정렬을 사용하여 시스템 데이터베이스를 만드는 경우에도 변경되지 않음) [mssqlsystemresource]데이터베이스가 일관성있게 유지 되기 때문입니다. Latin1_General_CI_AS_KS_WS모든 SQL Server 설치에 대해 데이터 정렬이 있습니다 (또는 확실히 나타납니다). 그렇지 않으면 SQL Server가 내부적으로 자체 관리하기가 어렵 기 때문에 (즉, 내부 논리에 사용되는 정렬 및 비교 규칙이 설치에 따라 변경되는 경우) 의미가 있습니다.

이러한 세부 사항을 직접 보는 방법

이러한 시스템 카탈로그 뷰에서 필드의 소스를 보려면 다음을 수행하십시오.

  1. SSMS의 쿼리 탭에서 "실제 실행 계획 포함"( CTRL-M) 의 쿼리 옵션을 활성화하십시오.
  2. 시스템 카탈로그 뷰 중 하나에서 하나의 필드를 선택하는 쿼리를 실행합니다 (실행 계획은 단일 필드조차도 엄청나게 크고 복잡하기 때문에 한 번에 하나의 필드 만 선택하는 것이 좋습니다. t 선택) :

    SELECT recovery_model_desc FROM sys.databases;
  3. "실행 계획"탭으로 이동
  4. 그래픽 실행 계획 영역을 마우스 오른쪽 단추로 클릭하고 "실행 계획 XML 표시 ..."를 선택하십시오.
  5. SSMS의 새 탭이 다음과 유사한 제목으로 열립니다. Execution plan.xml
  6. Execution plan.xml탭으로 이동
  7. <OutputList>태그 의 첫 번째 항목을 찾으십시오 (일반적으로 10 행과 20 행 사이에 있어야 함).
  8. <ColumnReference>태그 가 있어야합니다 . 해당 태그의 속성은 테이블의 특정 필드를 가리 키거나 계획에서 나중에 정의 된 표현식을 가리켜 야합니다.
  9. 속성이 실제 필드를 가리키는 경우 모든 정보가 있으므로 완료됩니다. 다음은 해당 recovery_model_desc필드 에 나타나는 것 입니다.

    <ColumnReference Database="[mssqlsystemresource]" Schema="[sys]"
                     Table="[syspalvalues]" Alias="[ro]" Column="name" />
  10. 대신 state_desc필드 를 선택한 경우와 같이 속성이 표현식을 가리키는 경우 처음에 다음을 찾을 수 있습니다.

    <ColumnReference Column="Expr1024" />
  11. 이 경우 계획의 나머지 부분을 정의하기 위해 계획의 나머지 부분을 살펴 봐야합니다 Expr1024. 이러한 참조가 여러 개있을 수 있지만 그 정의는 <OutputList>막을 수 없습니다 . 그러나 <ScalarOperator>정의가 포함 된 형제 요소가 있습니다. 다음은 해당 state_desc필드 에 나타나는 것 입니다.

    <ScalarOperator ScalarString="CASE WHEN serverproperty('EngineEdition')=5 AND [Expr1081]=(1) THEN N'RESTORING' ELSE CASE WHEN serverproperty('EngineEdition')=5 AND CONVERT(bit,[master].[sys].[sysdbreg].[status] as [d].[status]&amp;(128),0)=(1) THEN N'COPYING' ELSE CASE WHEN serverproperty('EngineEdition')=5 AND CONVERT(bit,[master].[sys].[sysdbreg].[status] as [d].[status]&amp;(256),0)=(1) THEN N'SUSPECT' ELSE [mssqlsystemresource].[sys].[syspalvalues].[name] as [st].[name] END END END">

데이터베이스 레벨 카탈로그 뷰의 소스도 점검 할 수 있습니다. 같은 개체에 대해 이렇게 sys.tables것을 뜻 쇼 name필드에서 비롯 [current_db].[sys].[sysschobjs]그동안 (는 데이터베이스의 데이터 정렬과 일치하는 데이터 정렬이 있습니다 이유입니다) lock_escalation_desc필드에서 온다 [mssqlsystemresource].[sys].[syspalvalues](그것이 데이터 정렬이 있습니다 이유입니다 Latin1_General_CI_AS_KS_WS).

Clippy는 "UNPIVOT 쿼리를 수행하려는 것 같습니다."

콜 레이션 우선 순위가 무엇이고 어떻게 작동하는지 알았으니, 그 지식을 UNPIVOT 쿼리에 적용 해 봅시다.

를 들어 UNPIVOT운영, SQL Server는 것 정말 각 소스 필드가 될 것을 : (필요 의미) 선호하는 동일한 유형 . 일반적으로 "type"은 기본 유형 (예 : VARCHAR/ NVARCHAR/ INT/ etc)을 나타내지 만 여기서는 SQL Server에도 COLLATION이 포함됩니다. 데이터 정렬이 제어하는 ​​VARCHAR의 문자 세트 (예 : 코드 페이지)와 문자의 동등성 및 문자 조합 (즉, 정규화)을 결정하는 언어 규칙을 고려할 때 이는 부당한 것으로 간주되어서는 안됩니다. 다음은 유니 코드 "정규화"가 무엇인지에 대한 mimi-primer입니다.

PRINT '---';
IF (N'aa' COLLATE Danish_Greenlandic_100_CI_AI = N'å' COLLATE Danish_Greenlandic_100_CI_AI)
     PRINT 'Danish_Greenlandic_100_CI_AI';
IF (N'aa' COLLATE SQL_Latin1_General_CP1_CI_AI = N'å' COLLATE SQL_Latin1_General_CP1_CI_AI)
     PRINT 'SQL_Latin1_General_CP1_CI_AI';
PRINT '---';
IF (N'of' COLLATE Upper_Sorbian_100_CI_AI =  N'öf' COLLATE Upper_Sorbian_100_CI_AI)
     PRINT 'Upper_Sorbian_100_CI_AI';
IF (N'of' COLLATE German_PhoneBook_CI_AI =  N'öf' COLLATE German_PhoneBook_CI_AI)
     PRINT 'German_PhoneBook_CI_AI';
PRINT '---';

보고:

---
Danish_Greenlandic_100_CI_AI
---
Upper_Sorbian_100_CI_AI
---

이제 원래 쿼리를 시작하겠습니다. 다양한 변화가 결과를 어떻게 변화시키는 지 확인하기 위해 몇 가지 테스트를 수행 한 다음, 몇 가지 변화만으로 결과를 해결할 수있는 방법을 살펴 보겠습니다.

  1. 첫 번째 오류는 CompatibilityLevel피벗되지 않는 두 번째 필드 인 필드에 관한 것이며 모든 문자열 리터럴을 포함하는 표현식입니다. 필드 참조가 없으면 결과 데이터 정렬은 "강제 기본값"으로 간주됩니다. 강제 기본값은 현재 데이터베이스의 데이터 정렬을 가져옵니다 SQL_Latin1_General_CP1_CI_AS. 다음 20 개 정도의 필드는 문자열 리터럴 일 뿐이므로 강제 기본값도 있으므로 충돌하지 않아야합니다. 우리가 첫 번째 필드에 돌아 보면하지만 recovery_model_desc,의 필드에서 직접 오는 것을 sys.databases그것에게 "암시"정렬하게, 이것은 않습니다 하지 로컬 DB의 정렬에 걸리지 만 대신 원래의 정렬입니다있어하는 유지 Latin1_General_CI_AS_KS_WS( 실제로 [mssqlsystemresource]DB 에서 나오기 때문입니다 ).

    따라서 필드 1 (RecoveryModel)이 Latin1_General_CI_AS_KS_WS필드 2 (CompatibilityLevel)가 SQL_Latin1_General_CP1_CI_AS인 경우 필드 2가 Latin1_General_CI_AS_KS_WS필드 1과 일치 하도록 강제 할 수 있어야 하며 필드 3 (AutoClose)에 대한 오류가 표시되어야합니다.

    CompatibilityLevel줄 끝에 다음을 추가하십시오 .
    COLLATE Latin1_General_CI_AS_KS_WS

    그런 다음 쿼리를 실행하십시오. 확실히, 오류는 이제 AutoClose충돌 이있는 필드임을 나타냅니다.

  2. 두 번째 테스트에서는 방금 변경 한 내용을 취소해야합니다 (예 : 줄 COLLATE끝 에서 절 제거) CompatibilityLevel.

    이제 SQL Server가 필드가 지정된 순서대로 실제로 평가하는 경우 필드 1 (RecoveryModel)을 제거 할 수 있어야합니다. 이렇게하면 현재 필드 2 (CompatibilityLevel)가 마스터 데이터 정렬을 설정하는 필드가됩니다. 결과 UNPIVOT. 이 CompatibilityLevel필드는 데이터베이스 조합을 수행하는 강제 기본값이므로 첫 번째 오류는PageVerify 필드 참조 . 필드 참조는 원래 데이터 정렬을 유지하는 암시 적 데이터 정렬 Latin1_General_CI_AS_KS_WS입니다. 현재 DB의 데이터 정렬

    따라서 (위쪽으로) , RecoveryModel에서 시작하여 줄 SELECT을 주석 처리 한 다음 아래 절 에서 RecoveryModel줄 을 주석 처리하고 다음 줄에서 UNPIVOT선행 쉼표를 제거하여 CompatibilityLevel구문 오류가 발생하지 않도록하십시오.

    해당 쿼리를 실행하십시오. 확실히, 오류는 이제 PageVerify충돌 이있는 필드임을 나타냅니다.

  3. 세 번째 테스트에서는 RecoveryModel필드 를 제거하기 위해 방금 변경 한 내용을 취소해야 합니다. 계속해서 쉼표를 넣고 다른 두 줄의 주석을 해제하십시오.

    이제 콜 레이션을 강제로 다른 방향으로 갈 수 있습니다. 강제적 인 기본 데이터 정렬 필드 (대부분의 필드)의 데이터 정렬을 변경하는 대신 내재 데이터 정렬 필드를 현재 DB의 데이터 정렬 필드로 변경할 수 있어야합니다.

    따라서 첫 번째 테스트와 마찬가지로 명시 적 COLLATE절을 사용하여 필드 1 (RecoveryModel)의 데이터 정렬을 강제 할 수 있어야합니다 . 그러나 특정 데이터 정렬을 지정한 다음 다른 데이터 정렬을 사용하여 데이터베이스에서 쿼리를 실행하면 강제 기본 기본 데이터 정렬 필드가 새 데이터 정렬을 선택하여이 첫 번째 필드를 설정하는 것과 충돌합니다. 그것은 고통처럼 보인다. 다행히도이를 처리하는 동적 방법이 있습니다. DATABASE_DEFAULT강제 기본 필드와 마찬가지로 현재 데이터베이스 데이터 정렬을 선택 하는 의사 데이터 정렬이 있습니다 .

    계속해서 다음과 같이 시작하는 행의 끝 부분에 다음을 추가하십시오 , RecoveryModel. COLLATE DATABASE_DEFAULT

    해당 쿼리를 실행하십시오. 물론 오류 PageVerify는 충돌 이 발생한 필드임을 다시 한 번 나타냅니다 .

  4. 최종 테스트를 위해 이전 변경 사항을 취소 할 필요가 없습니다.

    UNPIVOT쿼리 를 해결하기 위해 지금해야 할 일은 COLLATE DATABASE_DEFAULT나머지 암시 적 데이터 정렬 필드의 끝에 를 추가하는 것입니다 : PageVerifyRestrictedAccess. 그동안 Collation필드는 암시 적 데이터 정렬, 즉 필드에서 유래 master일반적으로 "현재"데이터베이스와 일치한다 데이터베이스. 그러나 이것이 항상 작동하도록 안전을 원한다면 COLLATE DATABASE_DEFAULT해당 필드의 끝에도 추가하십시오 .

    해당 쿼리를 실행하십시오. 물론 오류는 없습니다. 이 쿼리를 수정하는 COLLATE DATABASE_DEFAULT데 필요한 것은 3 개의 필드 (필수) 및 1 개 (옵션)의 끝에 추가 하는 것입니다.

  5. 선택적 테스트 : 이제 UNPIVOT 쿼리가 올바르게 작동하므로 다음과 같이 필드 정의 중 하나만 CONVERT(VARCHAR(50),대신로 변경 51하십시오 CONVERT(VARCHAR(51),.

    쿼리를 실행하십시오. The type of column "X" conflicts with the type of other columns specified in the UNPIVOT list.일치하지 않는 데이터 정렬 일 때 와 동일한 오류가 발생합니다.

    데이터 유형과 데이터 정렬 불일치에 대해 동일한 오류를 얻는 것이 실제로 도움이 될만큼 구체적이지 않습니다. 따라서 확실히 개선의 여지가 있습니다 :).


데이터 정렬에 대한 특정 질문보다 쿼리와 관련된 참고 사항 :

모든 소스 필드는 데이터 유형 NVARCHAR이므로 CONVERT모든 출력 필드가 NVARCHAR대신에 더 안전합니다 VARCHAR. 현재 비표준 ASCII 문자가 포함 된 데이터를 처리하지 않을 수도 있지만 시스템 메타 데이터를 사용하면 데이터 NVARCHAR(128)를 최소한 해당 필드의 최대 길이 인 최대 로 변환 할 수 있습니다. 향후 문제가 발생하지 않거나 시스템에 해당 문자가 이미있을 수있는이 코드를 복사하는 다른 사람에게는 문제가되지 않습니다.


5

이것은 질문에 대한 정답이 아닌 특정 문제에 대한 해결 방법 입니다. 다음 sql_variant대신 에 변환하여 오류를 피할 수 있습니다 varchar(50).

DECLARE @dbname SYSNAME;
SET @dbname = DB_NAME();

SELECT [Database]            = unpvt.DatabaseName
    , [Configuration Item]   = unpvt.OptionName
    , [Configuration Value]  = unpvt.OptionValue
    , [BaseType] = SQL_VARIANT_PROPERTY(unpvt.OptionValue, 'BaseType')
    , [MaxLength] = SQL_VARIANT_PROPERTY(unpvt.OptionValue, 'MaxLength')
    , [Collation] = SQL_VARIANT_PROPERTY(unpvt.OptionValue, 'Collation')
FROM (
    SELECT 
        DatabaseName = name 
        , RecoveryModel                 = CONVERT(sql_variant, d.recovery_model_desc)
        , CompatibilityLevel            = CONVERT(sql_variant, CASE d.[compatibility_level] WHEN 70 THEN 'SQL Server 7' WHEN 80 THEN 'SQL Server 2000' WHEN 90 THEN 'SQL Server 2005' WHEN 100 THEN 'SQL Server 2008' WHEN 110 THEN 'SQL Server 2012' WHEN 120 THEN 'SQL Server 2014' ELSE 'UNKNOWN' END)
        , AutoClose                     = CONVERT(sql_variant, CASE d.is_auto_close_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , AutoCreateStatistics          = CONVERT(sql_variant, CASE d.is_auto_create_stats_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , AutoShrink                    = CONVERT(sql_variant, CASE d.is_auto_shrink_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , AutoUpdateStatistics          = CONVERT(sql_variant, CASE d.is_auto_update_stats_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , AutoUpdateStatisticsAsynch    = CONVERT(sql_variant, CASE d.is_auto_update_stats_async_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , CloseCursorOnCommit           = CONVERT(sql_variant, CASE d.is_cursor_close_on_commit_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , DefaultCursor                 = CONVERT(sql_variant, CASE d.is_local_cursor_default WHEN 1 THEN 'LOCAL' ELSE 'GLOBAL' END)
        , ANSINULL_Default              = CONVERT(sql_variant, CASE d.is_ansi_null_default_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ANSINULLS_Enabled             = CONVERT(sql_variant, CASE d.is_ansi_nulls_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ANSIPadding_Enabled           = CONVERT(sql_variant, CASE d.is_ansi_padding_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ANSIWarnings_Enabled          = CONVERT(sql_variant, CASE d.is_ansi_warnings_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ArithmeticAbort_Enabled       = CONVERT(sql_variant, CASE d.is_arithabort_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , ConcatNullYieldsNull          = CONVERT(sql_variant, CASE d.is_concat_null_yields_null_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , CrossDBOwnerChain             = CONVERT(sql_variant, CASE d.is_db_chaining_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , DateCorrelationOptimized      = CONVERT(sql_variant, CASE d.is_date_correlation_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , NumericRoundAbort             = CONVERT(sql_variant, CASE d.is_numeric_roundabort_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , [Parameterization]            = CONVERT(sql_variant, CASE d.is_parameterization_forced WHEN 0 THEN 'SIMPLE' ELSE 'FORCED' END)
        , QuotedIdentifiers_Enabled     = CONVERT(sql_variant, CASE d.is_quoted_identifier_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , RecursiveTriggers_Enabled     = CONVERT(sql_variant, CASE d.is_recursive_triggers_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , [TrustWorthy]                 = CONVERT(sql_variant, CASE d.is_trustworthy_on WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , VARDECIMAL_Storage            = CONVERT(sql_variant, 'TRUE')
        , PageVerify                    = CONVERT(sql_variant, page_verify_option_desc  )
        , BrokerEnabled                 = CONVERT(sql_variant, CASE d.is_broker_enabled WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , DatabaseReadOnly              = CONVERT(sql_variant, CASE d.is_read_only WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , EncryptionEnabled             = CONVERT(sql_variant, CASE d.is_encrypted WHEN 0 THEN 'FALSE' ELSE 'TRUE' END)
        , RestrictedAccess              = CONVERT(sql_variant, user_access_desc)
        , Collation                     = CONVERT(sql_variant, d.collation_name)
    FROM sys.databases d
    WHERE name = @dbname
        OR @dbname IS NULL
    ) src
UNPIVOT
(
    OptionValue FOR OptionName IN
    (
        RecoveryModel
        , CompatibilityLevel
        , AutoClose
        , AutoCreateStatistics 
        , AutoShrink 
        , AutoUpdateStatistics 
        , AutoUpdateStatisticsAsynch 
        , CloseCursorOnCommit 
        , DefaultCursor 
        , ANSINULL_Default 
        , ANSINULLS_Enabled 
        , ANSIPadding_Enabled 
        , ANSIWarnings_Enabled 
        , ArithmeticAbort_Enabled 
        , ConcatNullYieldsNull 
        , CrossDBOwnerChain 
        , DateCorrelationOptimized 
        , NumericRoundAbort 
        , [Parameterization] 
        , QuotedIdentifiers_Enabled 
        , RecursiveTriggers_Enabled 
        , [TrustWorthy] 
        , VARDECIMAL_Storage 
        , PageVerify 
        , BrokerEnabled 
        , DatabaseReadOnly 
        , EncryptionEnabled 
        , RestrictedAccess 
        , Collation
    )
) AS unpvt;

기본 유형의 열에 대한 정보를 위해 3 개의 열을 추가했습니다 OptionValue.

샘플 출력

클라이언트가 sql_variant데이터를 처리 할 수없는 경우 unpvt.OptionValue열에서 최종 (최상위) 변환을 수행하십시오 ( 예 :) nvarchar(256).


4

좋아, 그래서 나는 보았다

sp_helptext [sys.databases]

그런 다음 기둥이 어디에서 왔는지 무너졌습니다. 을 가진 사람 Latin1_General_CI_AS_KS_WS정렬 모든 시스템 테이블에서 오는sys.syspalvalues 일반 조회 테이블을 것으로 보인다 (당신이 그것을보기 위해 DAC를 통해 연결해야합니다 있도록이 시스템 테이블입니다.).

내 생각 엔 그것이 Latin1_General_CI_AS_KS_WS 가능한 모든 조회 값을 처리하도록 있습니다. 그래도 어떻게 짜증나는지 알 수 있습니다.

정의를 보는 다른 방법 (원래 Max 에서 주석으로 제공)은 다음과 같습니다.

SELECT ObjectSchema = s.name
    , ObjectName = o.name
    , ObjectDefinition = sm.definition
FROM master.sys.all_sql_modules sm
    INNER JOIN master.sys.system_objects o ON sm.object_id = o.object_id
    INNER JOIN master.sys.schemas s ON o.schema_id = s.schema_id
WHERE s.name = 'sys' 
    AND o.name = 'databases';`
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.