Sys.databases dosyasındaki bazı sütunların harmanlanması nasıldır?


21

2005-2012 arasında değişen SQL Server'ın çeşitli sürümlerinde UNPIVOTbulunan çeşitli sütunlarda çalıştırmaya çalışıyorum sys.databases.

UNPIVOTAşağıdaki hata iletisiyle başarısız oluyor:

Msg 8167, Seviye 16, Durum 1, Satır 48

"CompatibilityLevel" sütununun türü, UNPIVOT listesinde belirtilen diğer sütunların türüyle çakışıyor.

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;

Bu, verilen veritabanı için aşağıdakilere benzer şekilde güzel biçimlendirilmiş bir veritabanı seçenekleri listesi sağlamak için tasarlanmıştır:

+----------+----------------------------+----------------------------+
| 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 |
+----------+----------------------------+----------------------------+

Ben Latin1_General_CI_AS_KS_WSharmanlama ile bir sunucuda çalıştırdığımda , ifade başarılı. T-SQL belirli alanların bir COLLATEyan tümcesi olacak şekilde değiştirirseniz, diğer harmanlamalara sahip sunucularda çalışır.

Harmanlama dışındaki sunucularda çalışan kod 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;

Gözlemlenen davranış, aşağıdaki alanların sunucu harmanlamasını veya veritabanı harmanlamasını gözlemlememesidir; onlar vardır her zaman sunulan Latin1_General_CI_AS_KS_WSharmanlama.

SQL Server 2012'de, sys.sp_describe_first_result_setbelirli bir sorgudan döndürülen sütunlar hakkında kolayca meta veriler elde etmek için kullanabiliriz . Harmanlama uyumsuzluğunu belirlemek için aşağıdakileri kullandım:

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;

Sonuçlar:

resim açıklamasını buraya girin

Bu sütunların harmanlaması neden statik olarak ayarlandı?

Yanıtlar:


17

Microsoft'un resmi sözcüğü:

Önceden tanımlanmış dizeler içeren sütunlardan bazıları (türler, sistem açıklamaları ve sabitler gibi) her zaman belirli bir harmanlamaya sabitlenir Latin1_General_CI_AS_KS_WS. Bu, örnek / veritabanı harmanlamadan bağımsızdır. Bunun nedeni, bunun sistem meta verileri (kullanıcı meta verileri değil) olması ve temelde bu dizelerin büyük / küçük harfe duyarlı olmamasıdır (anahtar kelimeler gibi, her zaman Latince).

Sistem tablolarında nesne adları, sütun adları, dizin adları, oturum açma adları vb. Gibi kullanıcı meta verileri içeren diğer sütunlar örneği veya veritabanı harmanlamasını alır. Sütunlar, örnek harmanlama durumunda SQL Server kurulumu sırasında ve veritabanı harmanlaması durumunda veritabanı oluşturulurken uygun harmanlamaya harmanlanır.

Siz sordunuz (benimkini vurgulayın):

Bu sütunların harmanlaması neden statik olarak ayarlandı?

Bazı sütunların statik olarak ayarlanmasının nedeni, sorguların doğru çalışması için sunucu veya veritabanı harmanlaması (daha önemlisi: CaSe SenSiTIviTy) konusunda endişelenmesine gerek olmamasıdır. Bu sorgu, harmanlamadan bağımsız olarak her zaman çalışır:

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

Sunucu harmanlama büyük / küçük harfe duyarlıysa, yukarıdaki sorgu tıpkı bunun gibi 0 satır döndürür:

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

Örneğin, SQL_Estonian_CP1257_CS_ASharmanlama ile bir SQL Server örneği yüklerseniz , aşağıdakileri çalıştırın:

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

Bu sonuçları (veya SQL Server sürümünüze bağlı olarak benzer bir şey) göreceksiniz:

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

Şimdi, sunucu harmanlamasını ana veritabanından devralmak yerine veritabanı harmanlamasını devralan meta veri görünümlerini göstermek için:

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

Sonuçlar:

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

Böylece, bu durumda birkaç sütun veritabanı harmanlamasını devralırken, diğerleri bu "genel" Latin1 harmanlamasına sabitlenir, yani belirli adları ve özellikleri yukarıda açıklanan vaka hassasiyeti sorunlarından yalıtmak için kullanılır.

Bir gerçekleştirmeye çalışırsanız UNION, örneğin:

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

Bu hatayı alıyorsunuz:

Msg 451, Seviye 16, Durum 1
SELECT deyimi sütun 1'de meydana gelen UNION ALL işlecinde "Albanian_BIN" ve "SQL_Estonian_CP1257_CS_AS" arasındaki harmanlama çakışması çözülemiyor.

Benzer şekilde, bir PIVOTveya gerçekleştirmeye çalışırsanız UNPIVOT, kurallar daha da katıdır (çıktı türlerinin yalnızca uyumlu olmak yerine tam olarak eşleşmesi gerekir ), ancak hata iletisi çok daha az yardımcı ve hatta yanıltıcıdır:

Msg 8167, Seviye 16, Durum 1
"Sütun adı" sütun türü, UNPIVOT listesinde belirtilen diğer sütunların türüyle çakışıyor.

COLLATESorgularınızdaki açık yan tümceleri kullanarak bu hataları gidermeniz gerekir. Örneğin, yukarıdaki birlik şu şekilde olabilir:

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;

Bu, sorunlara neden olabilecek tek zaman, bir harmanlama zorlanmış ancak aynı karakter temsilini içermiyorsa veya sıralama kullanılıyorsa ve zorlamalı harmanlama kaynaktan farklı bir sıralama düzeni kullanıyorsa kafa karıştırıcı çıktı elde edeceğinizdir.


7

Harmanlama Önceliğinin Arka Planı

Sistem kataloğu görünümlerindeki çeşitli alanların Harmanlanması ile ilgili olarak gördüğünüz davranış, her alanın nasıl tanımlandığı ve Harmanlama Önceliği'nin bir sonucudur.

Bakarken sys.databases, bunun bir masa olmadığını akılda tutmak önemlidir. Geçmişte (SQL Server 2000 ile biten bence) bunlar sistem katalog tablolarıyken , şimdi sistem katalog görünümleridir . Bu nedenle, içindeki bilgilerin kaynağı mutlaka geçerli veritabanı bağlamından (veya tam nitelikli bir nesne gibi belirtilen veritabanının bağlamından) gelmeyebilir master.sys.databases.

Özellikle ile ilgili olarak sys.databases, bazı alanlar [master]veritabanından geliyor (bu, örneğin varsayılan harmanlama temelinde bir harmanlama ile oluşturulmuştur - yani sunucu düzeyinde harmanlama), bazı alanlar ifadelerdir (yani CASEifadeler) ve bazıları geliyor "gizli" bir kaynaktan: [mssqlsystemresource]veritabanı. Ve [mssqlsystemresource]veritabanı bir harmanlama var Latin1_General_CI_AS_KS_WS.

nameAlan kaynak alındığı namealanda master.sys.sysdbreg. Bu nedenle, bu alan her zaman [master]veritabanının harmanlamasında olmalıdır , bu da yine sunucunun harmanlamasıyla eşleşecektir.

ANCAK, aşağıdaki alanlar sys.databasesgeliyor [name]alanda [mssqlsystemresource].[sys].[syspalvalues]:

  • user_access_desc
  • snapshot_isolation_state_desc
  • recovery_model_desc
  • page_verify_option_desc
  • log_reuse_wait_desc
  • containment_desc

Bu alanların her zaman bir harmanlaması olmalıdır Latin1_General_CI_AS_KS_WS.

Ancak collation_namealan aşağıdaki ifadeden gelir:

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)

Burada Harmanlama Önceliği devreye girmeye başlar. Buradaki çıktı için her iki seçenek de sistem işlevleridir: serverproperty()ve collationpropertyfromid(). Bu ifadenin harmanlaması "Zorunlu-varsayılan" olarak kabul edilir:

Herhangi bir Transact-SQL karakter dizesi değişkeni, parametre, değişmez ya da bir katalog yerleşik işlevi veya dize girişleri almayan ancak dize çıktısı üreten yerleşik bir işlev çıktısı.

Nesne kullanıcı tanımlı bir işlevde, saklı yordamda veya tetikleyicide bildirilirse, nesneye işlevin, saklı yordamın veya tetikleyicinin oluşturulduğu veritabanının varsayılan harmanlaması atanır. Nesne toplu olarak bildirilirse, nesneye bağlantı için geçerli veritabanının varsayılan harmanlaması atanır.

Bu 2. paragraf ışığında sys.databases, masterveritabanında var olan bir görünüm olduğundan, veritabanının harmanlanmasını alır master(geçerli veritabanını değil).

state_descAlanı da ifadesidir:

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

Ancak, bu ifade üzerindeki harmanlamadır Latin1_General_CI_AS_KS_WS. Neden? Bu ifadede yeni bir şey tanıtıldı: gerçek bir alana referans: [mssqlsystemresource].[sys].[syspalvalues].[name]o son ELSEmaddede. Sütun referansları "Örtük" olarak kabul edilir:

Bir sütun başvurusu. İfadenin harmanlaması, tablo veya görünümdeki sütun için tanımlanan harmanlamadan alınır.

Tabii ki, bu ilginç bir soru açar: Bu ifadenin, nasıl CASEdeğerlendirildiğine bağlı olarak farklı bir harmanlama döndürmesi mümkün müdür ? Değişmez değerler, bu nesnenin tanımlandığı veritabanının harmanlamasında olacaktır, ancak ELSEkoşul, orijinal harmanlamasını koruması gereken bir alan değeri döndürür. Neyse ki, sys.dm_exec_describe_first_result_set Dinamik Yönetim İşlevini kullanarak bir testi simüle edebiliriz :

-- 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

Döndürür (harmanlama ile ayarlanmış SQL_Latin1_General_CP1_CI_ASancak harmanlama ile bir veritabanında çalışan bir örnekte 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

Burada, alana atıfta bulunan iki sorgunun veritabanının [msdb]harmanlamasını aldığını görüyoruz [msdb](ki bu bir sistem DB'si olarak sunucu harmanlaması tarafından belirlendi).

Orijinal Soru ile ilgili

Gözlemlenen davranış, aşağıdaki alanların sunucu harmanlamasını veya veritabanı harmanlamasını gözlemlememesidir; onlar vardır her zaman sunulan Latin1_General_CI_AS_KS_WSharmanlama.

Gözleminiz yerinde: bu alanların Latin1_General_CI_AS_KS_WSsunucu harmanlama veya veritabanı harmanlamadan bağımsız olarak her zaman harmanlaması vardır. Ve nedeni: Harmanlama Önceliği. Bu alanlar [mssqlsystemresource]veritabanındaki bir tablodan gelir COLLATEve en yüksek önceliğe sahip olduğu için açık bir cümle ile geçersiz kılınmadıkça bu ilk harmanlamayı korur :

Explicit = İfadede bir COLLATE deyimi kullanılarak açıkça belirli bir harmanlamaya atanan ifade.

Açık, örtük olandan daha önceliklidir. Örtük, Zorunlu-varsayılandan önceliklidir:
Açık> Örtük> Zorunlu-varsayılan

Ve ilgili soru:

Bu sütunların harmanlaması neden statik olarak ayarlandı?

Statik olarak ayarlanmış olmaları veya diğer alanların bir şekilde dinamik olması değildir. Tüm bu sistem kataloğu görünümlerindeki tüm alanlar, aynı Harmanlama Önceliği kuralları üzerinde çalışmaktadır. Diğer alanlardan daha "statik" görünmelerinin nedeni (SQL Server'ı farklı bir varsayılan harmanlama ile yükleseniz bile değişmez, bu da sistem veritabanlarını bu varsayılan harmanlama ile oluşturur) [mssqlsystemresource]veritabanının sürekli olarak Latin1_General_CI_AS_KS_WSSQL Server'ın herhangi bir yüklemesinde bir harmanlama vardır (ya da kesinlikle görünür). Ve bu mantıklıdır çünkü aksi takdirde SQL Server'ın dahili olarak kendini yönetmesi zor olacaktır (örn. Dahili mantık için kullanılan sıralama ve karşılaştırma kuralları kuruluma göre değişiyorsa).

Bu özellikleri kendiniz nasıl görebilirsiniz?

Bu sistem kataloğu görünümlerinden herhangi birinde herhangi bir alanın kaynağını görmek istiyorsanız, aşağıdakileri yapmanız yeterlidir:

  1. SSMS'deki bir sorgu sekmesinde "Gerçek Yürütme Planını Dahil Et" ( CTRL-M) Sorgu Seçeneğini etkinleştirin ( )
  2. Sistem kataloğu görünümlerinden birinden bir alan seçerek bir sorgu yürütün (Yürütme planı tek bir alan için bile gülünç derecede büyük / karmaşık olduğundan ve aynı anda birçok alana referans içerdiğinden, her seferinde yalnızca bir alan seçmenizi öneririm. t seçimi):

    SELECT recovery_model_desc FROM sys.databases;
  3. "Uygulama planı" sekmesine gidin
  4. Grafik Yürütme planı alanına sağ tıklayın ve "Yürütme Planı XML'sini Göster ..." seçeneğini seçin.
  5. SSMS'de yeni bir sekme açılarak aşağıdakine benzer bir başlık açılır: Execution plan.xml
  6. Execution plan.xmlSekmeye git
  7. Bir <OutputList>etiketin ilk oluşumunu arayın (genellikle 10 ve 20 satırları arasında olmalıdır)
  8. Bir <ColumnReference>etiket olmalı . Bu etiketteki nitelikler ya tablodaki belirli bir alanı işaret etmeli ya da planın ilerisinde tanımlanmış bir ifadeyi göstermelidir.
  9. Öznitelikler gerçek bir alana işaret ediyorsa, tüm bilgileri içerdiği için işiniz tamamlanır. Alan için aşağıdakiler gösterilir recovery_model_desc:

    <ColumnReference Database="[mssqlsystemresource]" Schema="[sys]"
                     Table="[syspalvalues]" Alias="[ro]" Column="name" />
  10. Nitelikler, state_descalanı seçtiyseniz gibi bir ifadeyi gösteriyorsa, başlangıçta şunları bulacaksınız:

    <ColumnReference Column="Expr1024" />
  11. Bu durumda, planın geri kalanını tanımlamak Expr1024veya ortaya çıkan # ile bakmak gerekir. Bu referanslardan birkaçının olabileceğini, ancak tanımın bir <OutputList>blokta olmayacağını unutmayın . Ancak, <ScalarOperator>tanımı içeren bir kardeş öğeye sahip olacaktır . Alan için aşağıdakiler gösterilir 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">

Veritabanı düzeyinde katalog görünümlerinin kaynağını da kontrol etmek için aynı şey yapılabilir. Bunun gibi bir nesne için sys.tablesyapılması, namealanın geldiğini gösterecektir [current_db].[sys].[sysschobjs](bu nedenle veritabanının harmanlama ile eşleşen bir harmanlama vardır), lock_escalation_descalan gelirken [mssqlsystemresource].[sys].[syspalvalues](bu yüzden bir harmanlama vardır Latin1_General_CI_AS_KS_WS).

Clippy, "Görünüşe göre UNPIVOT sorgusu yapmak istiyormuşsunuz gibi görünüyor."

Şimdi Harmanlama Önceliğinin ne olduğunu ve nasıl çalıştığını bildiğimize göre, bu bilgiyi UNPIVOT sorgusuna uygulayalım.

Bir UNPIVOTişlem için SQL Server , her kaynak alanının tam olarak aynı türde olmasını gerçekten tercih eder (yani: gerektirir) . Genellikle "tür" temel tür (yani / / / etc) anlamına gelir, ancak burada SQL Server COLLATION içerir. Harmanlamaların neyi kontrol ettiği göz önüne alındığında bu mantıksız görülmemelidir: VARCHAR için karakter kümesi (yani Kod Sayfası) ve karakterlerin denkliğini ve karakter kombinasyonlarını belirleyen dil kuralları (yani normalleştirme). Aşağıdaki Unicode "normalleşmesi" ne mimi-primer:VARCHARNVARCHARINT

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 '---';

İadeler:

---
Danish_Greenlandic_100_CI_AI
---
Upper_Sorbian_100_CI_AI
---

Şimdi orijinal sorgunuzu başlatalım. Çeşitli değişikliklerin sonucu nasıl değiştirdiğini görmek için birkaç test yapacağız ve daha sonra birkaç değişikliğin bunu nasıl düzeltebileceğini göreceğiz.

  1. İlk hata, CompatibilityLevelaçıklanamayan ikinci alan olan alanla ilgilidir ve tüm dize değişmezlerini içeren bir ifade olur. Alan referansları olmadan, sonuçta elde edilen harmanlama "zorunlu-varsayılan" olarak kabul edilir). Zorunlu varsayılanlar, geçerli veritabanının harmanlanmasını üstlenelim SQL_Latin1_General_CP1_CI_AS. Sonraki 20 veya daha fazla alan da yalnızca dize değişmezleridir ve bu nedenle de zorunlu varsayılanlardır, bu nedenle çakışma olmamalıdır. Biz ilk alana geri bakarsanız, recovery_model_desc, bir alanın doğrudan geldiğini sys.databasesbir "örtülü" harmanlama yapar ve bu yok değil yerel DB'ın harmanlama almak, ama bunun yerine orijinal harmanlama olduğu oluyor ki korur Latin1_General_CI_AS_KS_WS( çünkü gerçekten [mssqlsystemresource]DB'den geliyor ).

    Bu nedenle, alan 1 (RecoveryModel) Latin1_General_CI_AS_KS_WSve alan 2 (CompatibilityLevel) ise SQL_Latin1_General_CP1_CI_AS, alan 2'yi Latin1_General_CI_AS_KS_WSalan 1 ile eşleşmeye zorlayabilmeliyiz ve sonra alan 3 (Otomatik Kapatma) için hata görünmelidir.

    CompatibilityLevelSatırın sonuna aşağıdakileri ekleyin :
    COLLATE Latin1_General_CI_AS_KS_WS

    Ve sonra sorguyu çalıştırın. Elbette, hata şimdi AutoCloseçatışmanın olduğu alan olduğunu söylüyor.

  2. İkinci testimiz için az önce yaptığımız değişikliği geri almamız gerekiyor (yani, COLLATEmaddeyi CompatibilityLevelsatırın sonundan kaldırmalıyız) .

    Şimdi, SQL Server alanların belirtildiği sıraya göre gerçekten değerlendiriliyorsa, geçerli alan 2'nin (CompatibilityLevel) ana harmanlama ayarını yapan alan olmasını sağlayacak alan 1'i (RecoveryModel) kaldırabilmeliyiz. sonuçta ortaya çıkan UNPIVOT. Ve CompatibilityLevelalan, veritabanı harmanlamasını alan bir zorunlu varsayılan değerdir, bu nedenle ilk hata PageVerify, bu alanın olduğu ve olmayan orijinal harmanlamayı koruyan örtük bir harmanlama olan bir alan referansı olan alan olmalıdır Latin1_General_CI_AS_KS_WS. geçerli DB'nin harmanlanması.

    Şimdi git ve ile başlayan satırını açıklama , RecoveryModeliçinde SELECT(üst doğru) ve sonra dışarı RecoveryModelsatırı UNPIVOTaşağıda madde ve aşağıdaki hattan gelen virgül kaldırmak CompatibilityLevelEğer bir sözdizimi hatası alamadım böylece.

    Bu sorguyu çalıştırın. Elbette, hata şimdi PageVerifyçatışmanın olduğu alan olduğunu söylüyor.

  3. Üçüncü testimiz için, RecoveryModelalanı kaldırmak için yaptığımız değişiklikleri geri almamız gerekiyor . Öyleyse devam edin ve virgül koyun ve diğer iki çizgiyi de kaldırın.

    Şimdi bir harmanlama zorlayarak diğer yöne gidebiliriz. Zorunlu-varsayılan harmanlama alanlarının (çoğu) harmanlamasını değiştirmek yerine, örtük harmanlama alanlarını mevcut DB alanıyla değiştirebilmeliyiz, değil mi?

    Bu nedenle, ilk testimiz gibi, alan 1'in (RecoveryModel) harmanlanmasını açık bir COLLATEcümle ile zorlayabilmeliyiz . Ancak, belirli bir harmanlama belirtirsek ve ardından sorguyu farklı bir harmanlama içeren bir veritabanında çalıştırırsak, zorunlu varsayılan harmanlama alanları, daha sonra bu ilk alanı ayarladığımız şeyle çakışacak yeni harmanlamayı alır. Bu bir acı gibi görünüyor. Neyse ki, bununla başa çıkmanın dinamik bir yolu var. DATABASE_DEFAULTGeçerli veritabanlarının harmanlamasını alan (tıpkı zorunlu varsayılan alanların yaptığı gibi) denilen sözde bir harmanlama vardır .

    Devam edin ve aşağıdakilerle başlayan satırın sonuna, yukarı doğru ekleyin , RecoveryModel: COLLATE DATABASE_DEFAULT

    Bu sorguyu çalıştırın. Elbette, hata bir kez daha PageVerifyçatışmanın olduğu alan olduğunu belirtir.

  4. Son test için, önceki değişikliklerin hiçbirini geri almamız gerekmez.

    Bu UNPIVOTsorguyu düzeltmek için tek yapmamız gereken COLLATE DATABASE_DEFAULT, kalan örtülü harmanlama alanlarının sonuna: PageVerifyve eklemektir RestrictedAccess. CollationAlan aynı zamanda örtük bir harmanlama olsa da, bu alan mastergenellikle "geçerli" veritabanı ile uyumlu olan veritabanından gelir. Ancak, bu her zaman işe yarayacak şekilde güvende olmak istiyorsanız COLLATE DATABASE_DEFAULT, o alanın sonuna da ekleyin .

    Bu sorguyu çalıştırın. Elbette, hata yok. Bu sorguyu düzeltmek COLLATE DATABASE_DEFAULTiçin gereken tek şey 3 alanın sonuna (zorunlu) ve belki 1 tane daha (isteğe bağlı) eklemekti .

  5. Opsiyonel Testi: Artık nihayet doğru çalıştığından UNPIVOT sorgusu, değişim ile başlayan saha tanımların herhangi birinin sadece bir olduğunu CONVERT(VARCHAR(50),bunun yerine olmak 51gibi: CONVERT(VARCHAR(51),.

    Sorguyu çalıştırın. The type of column "X" conflicts with the type of other columns specified in the UNPIVOT list.Yalnızca eşleşmeyen harmanlama olduğunda aldığınız aynı hatayı almalısınız .

    Hem veri türü hem de harmanlama uyumsuzlukları için aynı hatayı almak, gerçekten yardımcı olacak kadar spesifik değildir. Yani kesinlikle orada iyileştirilmesi için yer var :).


Sorgu ile ilgili Not Harmanlama ile ilgili belirli Sorudan daha fazlası:

Tüm kaynak alanları veri tipinde olduğundan NVARCHAR, yerine CONVERTtüm çıktı alanlarına daha güvenli olacaktır . Şu anda standart olmayan ASCII karakterleri olan verilerle ilgilenmiyor olabilirsiniz, ancak sistem meta verileri, bu alanların en azından bu alanlardan herhangi birinin en büyük maksimum uzunluğuna dönüşmesine izin veriyor - en azından gelecekte sizin için veya bu kodu kopyalayan ve sistemlerinde bu karakterlerden bazılarına sahip olabilecek herhangi bir kişi için bir sorun olmayacağını garanti eder.NVARCHARVARCHARNVARCHAR(128)


5

Bu, soruya tam bir cevap vermek yerine belirli bir sorun için geçici bir çözümdür. Şu sql_variantyerine dönüştürerek hatayı önleyebilirsiniz 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;

OptionValueSütunun temel türü hakkında bilgi için üç sütun ekledim .

Örnek çıktı

İstemci sql_variantverileri işleyemiyorsa, unpvt.OptionValuesütunda nihai (üst düzey) bir dönüştürme yapın, örn nvarchar(256).


4

Tamam, bir göz attım

sp_helptext [sys.databases]

sonra sütunların nereden geldiği bozuldu. Olanlar Latin1_General_CI_AS_KS_WSharmanlama tüm sistem tablosundan geliyor sys.syspalvaluesgenel bir arama tablosu olarak görünmektedir (görmek için DAC üzerinden bağlanmak zorunda kalacak yüzden, bir sistem tablosu bu.).

Benim tahminim, Latin1_General_CI_AS_KS_WSolası arama değerlerini işlemek için ayarlanmış olmasıdır . Yine de nasıl sinir bozucu olacağını görebiliyorum.

Tanımı görmenin başka bir yolu (başlangıçta Max tarafından bir yorumda sağlanan ):

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';`
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.