Sys.dat डेटाबेस में कुछ कॉलम के टकराने से क्या होगा?


21

मैं 2005 से 2012 तक SQL सर्वर के विभिन्न संस्करणों UNPIVOTमें समाहित विभिन्न स्तंभों पर चलने का प्रयास कर रहा हूं sys.databases

UNPIVOTनिम्न त्रुटि संदेश के साथ विफल हो रहा है:

Msg 8167, स्तर 16, राज्य 1, लाइन 48

स्तंभ का प्रकार "संगतता" UNPIVOT सूची में निर्दिष्ट अन्य स्तंभों के प्रकार के साथ संघर्ष करता है।

टी-एसक्यूएल:

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खंड हो, तो यह उन सर्वरों पर चलेगा जिनमें अन्य टकराव हैं।

कोड है कि सर्वर पर काम करता है के अलावा अन्य के साथ 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 सर्वर 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 सर्वर की स्थापना के समय स्तंभों को उचित समतलीकरण के लिए एकत्र किया जाता है।

आपने पूछा (जोर देकर):

इन स्तंभों का टकराव सांख्यिकीय रूप से क्यों निर्धारित किया गया है?

कारण यह है कि कुछ कॉलम सांख्यिकीय रूप से सेट किए गए हैं ताकि प्रश्नों को सही ढंग से काम करने के लिए सर्वर या डेटाबेस के कोलाजेशन (अधिक महत्वपूर्ण रूप से: सीसेसेटीवीटीवाई) के बारे में चिंता करने की आवश्यकता न हो। यह क्वेरी हमेशा टकराव की परवाह किए बिना काम करेगी:

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

जबकि यदि सर्वर कोलाज केस संवेदी था, तो ऊपर दी गई क्वेरी 0 पंक्तियाँ लौटाएगी, ठीक इसी तरह:

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

उदाहरण के लिए, यदि आप SQL सर्वर का SQL_Estonian_CP1257_CS_ASकोलाजेशन के साथ इंस्टाल करते हैं , तो निम्न कार्य करें:

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

आपको ये परिणाम (या SQL सर्वर के आपके संस्करण के आधार पर कुछ समान) दिखाई देंगे:

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

तो आप देख सकते हैं कि इस मामले में कई कॉलम डेटाबेस कोलाजेशन को विरासत में लेते हैं, जबकि अन्य इस "जेनेरिक" लैटिन 1 कोलाज के लिए तय किए गए हैं, जिसका अर्थ ऊपर वर्णित संवेदनशीलता मामलों से कुछ नामों और गुणों को इन्सुलेट करने के लिए किया जाता है।

यदि आप UNIONउदाहरण के लिए, प्रदर्शन करने की कोशिश करते हैं :

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

आपको यह त्रुटि मिलती है:

Msg 451, स्तर 16, राज्य 1
"अल्बानियाई_BIN" और "SQL_Estonian_CP1257_CS_AS" के बीच टकराव के संघर्ष को हल नहीं कर सकते हैं SELECT स्टेटमेंट कॉलम 1 में होने वाले सभी ऑपरेटर।

इसी तरह, यदि आप PIVOTया तो प्रदर्शन करने की कोशिश करते हैं UNPIVOT, तो नियम और भी कड़े हैं (आउटपुट प्रकारों को केवल संगत होने के बजाय बिल्कुल मेल खाना चाहिए ), लेकिन त्रुटि संदेश बहुत कम सहायक है, और भ्रामक भी है:

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

यदि आप एक टकराव के लिए मजबूर होते हैं, लेकिन एक ही वर्ण प्रतिनिधित्व नहीं होता है, या यदि छँटाई का उपयोग किया जाता है और मजबूर collation स्रोत से भिन्न क्रम क्रम का उपयोग नहीं करता है, तो केवल यह समस्या पैदा कर सकता है।


7

Collation Precedence पर पृष्ठभूमि

सिस्टम कैटलॉग दृश्य में विभिन्न फ़ील्ड्स के Collation के संबंध में आपके द्वारा देखे जा रहे व्यवहार का परिणाम है कि प्रत्येक फ़ील्ड कैसे परिभाषित की गई है और Collation Precedence।

देखते समय 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
  • containment_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)

यहीं से Collation Precedence आना शुरू होता है। आउटपुट के लिए दोनों विकल्प यहां सिस्टम फंक्शन हैं: serverproperty()और collationpropertyfromid()। इस अभिव्यक्ति के टकराने को "Coercible-default" माना जाता है:

किसी भी 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शर्त एक फ़ील्ड मान लौटाती है जिसे इसके मूल टकराव को बनाए रखना चाहिए। सौभाग्य से, हम sysinos_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](जो, सिस्टम डीबी होने के नाते, सर्वर कोलेशन द्वारा निर्धारित किए गए थे)।

मूल प्रश्न से संबंधित

देखा गया व्यवहार यह है कि निम्नलिखित फ़ील्ड या तो सर्वर कॉलेशन, या डेटाबेस कॉलेशन का निरीक्षण नहीं करते हैं; उन्हें हमेशा टकराव में प्रस्तुत किया जाता है Latin1_General_CI_AS_KS_WS

आपका अवलोकन स्पॉट-ऑन है: उन क्षेत्रों में हमेशा एक टकराव होता है Latin1_General_CI_AS_KS_WS, चाहे सर्वर से टकराव या डेटाबेस का टकराव हो। और इसका कारण है: Collation Precedence। वे फ़ील्ड [mssqlsystemresource]डेटाबेस में एक तालिका से आते हैं , और उस प्रारंभिक टकराव को तब तक बनाए रखेंगे जब तक कि एक स्पष्ट COLLATEक्लॉज के साथ ओवरराइड नहीं किया जाता है क्योंकि इसकी उच्चतम प्राथमिकता है:

स्पष्ट = एक अभिव्यक्ति जो स्पष्ट रूप से अभिव्यक्ति में COLLATE क्लॉज का उपयोग करके एक विशिष्ट टकराव के लिए डाली जाती है।

निहितार्थ पर स्पष्टता पूर्ववर्ती है। इंप्लिक्ट को कोरिसेबल-डिफॉल्ट पर वरीयता मिलती है:
स्पष्ट> इम्प्लिक्ट> कोरिसेबल-डिफॉल्ट

और संबंधित प्रश्न:

इन स्तंभों का टकराव सांख्यिकीय रूप से क्यों निर्धारित किया गया है?

ऐसा नहीं है कि वे सांख्यिकीय रूप से सेट हैं, न ही कि अन्य क्षेत्र किसी तरह गतिशील हैं। उन सभी सिस्टम कैटलॉग दृश्य में सभी फ़ील्ड Collation Precedence के समान नियमों पर काम कर रहे हैं। कारण यह है कि वे अन्य क्षेत्रों की तुलना में अधिक "स्थिर" दिखाई देते हैं (यानी वे भिन्न डिफ़ॉल्ट टकराव के साथ SQL सर्वर स्थापित करने पर भी नहीं बदलते हैं, जो बदले में उस डिफ़ॉल्ट टकराव के साथ सिस्टम डेटाबेस बनाता है) वह है [mssqlsystemresource]डेटाबेस लगातार Latin1_General_CI_AS_KS_WSSQL सर्वर की किसी भी स्थापना के पार (या तो यह निश्चित रूप से प्रकट होता है)। और यह समझ में आता है क्योंकि अन्यथा SQL सर्वर के लिए खुद को आंतरिक रूप से प्रबंधित करना मुश्किल होगा (यानी अगर स्थापना के आधार पर आंतरिक तर्क के लिए उपयोग किए जाने वाले सॉर्टिंग और तुलना नियम)।

इन बारीकियों को खुद कैसे देखें

यदि आप इन सिस्टम कैटलॉग के किसी भी दृश्य में किसी भी क्षेत्र (ओं) के स्रोत को देखना चाहते हैं, तो बस निम्नलिखित कार्य करें:

  1. SSMS में एक क्वेरी टैब में, "वास्तविक निष्पादन योजना शामिल करें" ( CTRL-M) के क्वेरी विकल्प को सक्षम करें ( )
  2. सिस्टम कैटलॉग दृश्यों में से एक से एक फ़ील्ड का चयन करते हुए एक क्वेरी निष्पादित करें (मैं एक समय में सिर्फ एक फ़ील्ड का चयन करने की सलाह देता हूं क्योंकि निष्पादन योजना केवल एक क्षेत्र के लिए बहुत बड़ी / जटिल है, और इसमें आपके द्वारा उत्पन्न कई क्षेत्रों के संदर्भ शामिल होंगे ' टी चयन):

    SELECT recovery_model_desc FROM sys.databases;
  3. "निष्पादन योजना" टैब पर जाएं
  4. चित्रमय निष्पादन योजना क्षेत्र में राइट-क्लिक करें और "एक्ज़ीक्यूटिव प्लान एक्सएमएल दिखाएँ ..." चुनें
  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)।

क्लिप्पी कहते हैं, "ऐसा लगता है कि आप एक UNPIVOT क्वेरी करना चाहते हैं।"

अब जब हम जानते हैं कि Collation Precedence क्या है और यह कैसे काम करता है, तो आइए उस ज्ञान को UNPIVOT क्वेरी में लागू करें।

एक UNPIVOTऑपरेशन के लिए, SQL सर्वर वास्तव में पसंद करने के लिए लगता है (अर्थ: की आवश्यकता है) कि प्रत्येक स्रोत फ़ील्ड बिल्कुल उसी प्रकार का हो । आमतौर पर "प्रकार" आधार प्रकार (अर्थात VARCHAR/ NVARCHAR/ INT/ आदि) को संदर्भित करता है लेकिन यहाँ SQL सर्वर भी COLLATION सहित है। इसे अनुचित के रूप में नहीं देखा जाना चाहिए कि कोलाज़ क्या नियंत्रित करता है: वर्ण के लिए वर्ण सेट (अर्थात कोड पृष्ठ), और भाषाई नियम जो पात्रों के संयोजन और वर्णों के संयोजन (यानी सामान्यीकरण) को निर्धारित करते हैं। निम्नलिखित यूनिकोड "सामान्यीकरण" पर एक मिमी-प्राइमर है:

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]डीबी से आ रहा है )।

    तो, यदि फ़ील्ड 1 (RecoveryModel) है Latin1_General_CI_AS_KS_WS, और फ़ील्ड 2 (संगतता) है 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. हमारे दूसरे परीक्षण के लिए हमें अपने द्वारा किए गए परिवर्तन को पूर्ववत करने की आवश्यकता है (अर्थात हटाएं COLLATECompatibilityLevel पंक्ति के अंत से खंड को ।

    अब, यदि SQL सर्वर वास्तव में उस क्रम में मूल्यांकन कर रहा है जिसमें फ़ील्ड निर्दिष्ट किए गए हैं, तो हमें फ़ील्ड 1 (पुनर्प्राप्तिमॉडल) को हटाने में सक्षम होना चाहिए, जो वर्तमान फ़ील्ड 2 (संगतता) का कारण होगा वह क्षेत्र जो मास्टर विभाजन का निर्धारण करता है परिणामी UNPIVOT और यहCompatibilityLevel क्षेत्र एक सहकर्मी-डिफ़ॉल्ट है जो डेटाबेस कोलाजेशन पर ले जाता है, इसलिए पहली त्रुटि PageVerifyफ़ील्ड होनी चाहिए , जो एक फ़ील्ड संदर्भ है, जो एक अंतर्निहित टकराव है जो मूल टकराव को बनाए रखता है, जो इस मामले में है Latin1_General_CI_AS_KS_WSऔर जो नहीं है वर्तमान DB की टक्कर।

    तो आगे बढ़िए और रेखा के साथ शुरू बाहर टिप्पणी , RecoveryModelमें SELECT(ऊपर की ओर) और फिर बाहर टिप्पणी RecoveryModelमें लाइनUNPIVOT नीचे खंड और निम्नलिखित लाइन से अग्रणी अल्पविराम को दूर CompatibilityLevelइतना है कि आप एक सिंटैक्स त्रुटि नहीं मिलता है।

    उस क्वेरी को चलाएं। निश्चित रूप से, त्रुटि अब बताती है कि यह वह PageVerifyक्षेत्र है जिसमें संघर्ष है।

  3. हमारे तीसरे परीक्षण के लिए, हमें उन परिवर्तनों को पूर्ववत् करने की आवश्यकता है जो हमने अभी हटाने के लिए किए थे RecoveryModel क्षेत्र । तो आगे बढ़ो और अल्पविराम को वापस रखो, और उन दो अन्य लाइनों को अनसुना करें।

    अब हम एक टकराव को मजबूर करने के साथ दूसरी दिशा में जा सकते हैं। कोरिसेबल-डिफॉल्ट कॉलेशन फ़ील्ड्स (जो उनमें से अधिकांश हैं) के टकराव को बदलने के बजाय, हमें अंतर्निहित डीबी को वर्तमान डीबी के रूप में बदलने में सक्षम होना चाहिए, है ना?

    इसलिए, हमारे पहले परीक्षण की तरह, हमें स्पष्ट रूप से फ़ील्ड 1 (RecoveryModel) के संयोजन को बाध्य करने में सक्षम होना चाहिए COLLATE क्लॉज़ के । लेकिन अगर हम एक विशेष टकराव को निर्दिष्ट करते हैं और फिर एक डेटाबेस में क्वेरी को एक अलग कोलाजेशन के साथ चलाते हैं, तो कोरिसेबल-डिफॉल्ट कोलाजेशन फ़ील्ड नए कोलाज को उठाएगा जो कि हम इस पहले फ़ील्ड को सेट करने के साथ संघर्ष करेंगे। जो दर्द की तरह लगता है। सौभाग्य से, इससे निपटने का एक गतिशील तरीका है। एक छद्म कोलाजेशन कहा जाता है DATABASE_DEFAULTजो वर्तमान डेटाबेस कोलाज को उठाता है (ठीक वैसे ही जैसे कोरिसेबल-डिफॉल्ट फील्ड करते हैं)।

    आगे बढ़ो और पंक्ति के अंत में निम्नलिखित जोड़ो, शीर्ष की ओर, जो इसके साथ शुरू होता है , RecoveryModel: COLLATE DATABASE_DEFAULT

    उस क्वेरी को चलाएं। निश्चित रूप से, त्रुटि एक बार फिर से बताती है कि यह वह PageVerifyक्षेत्र है जिसमें संघर्ष है।

  4. अंतिम परीक्षण के लिए, हमें किसी भी पूर्व परिवर्तन को पूर्ववत करने की आवश्यकता नहीं है।

    इस UNPIVOTक्वेरी को ठीक करने के लिए अब हमें बस इतना करना COLLATE DATABASE_DEFAULTहै कि शेष अंतर्निहित टकराव के क्षेत्रों के अंत में जोड़ना है : PageVerifyऔर RestrictedAccess। जबकि Collationफ़ील्ड भी एक अंतर्निहित टकराव है, वह क्षेत्र masterडेटाबेस से आता है , जो आमतौर पर "वर्तमान" डेटाबेस के अनुरूप होता है। लेकिन, यदि आप सुरक्षित रहना चाहते हैं ताकि यह हमेशा काम करे, तो आगे बढ़ें और COLLATE DATABASE_DEFAULTसाथ ही साथ उस क्षेत्र के अंत में भी जोड़ें।

    उस क्वेरी को चलाएं। निश्चित रूप से पर्याप्त, कोई त्रुटि नहीं। इस क्वेरी को ठीक करने में लगने वाले सभी COLLATE DATABASE_DEFAULT3 फ़ील्ड (आवश्यक) और शायद 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.त्रुटि मिलनी चाहिए जो आपको तब मिली थी जब यह केवल मिलीभगत थी जो मेल नहीं खा रही थी।

    डेटाटाइप और कोलाज मिसमैच दोनों के लिए समान त्रुटि प्राप्त करना वास्तव में उपयोगी होने के लिए पर्याप्त विशिष्ट नहीं है। तो वहाँ निश्चित रूप से सुधार की गुंजाइश है :)।


Collation के बारे में विशिष्ट प्रश्न से अधिक प्रश्न से संबंधित नोट:

चूंकि सभी स्रोत फ़ील्ड डेटाटाइप के हैं NVARCHAR, इसलिए इसके बजाय यह CONVERTसभी आउटपुट फ़ील्ड के लिए सुरक्षित होगा । आप उस समय डेटा के साथ व्यवहार नहीं कर सकते हैं जिसमें कोई भी गैर-मानक-ASCII वर्ण हैं, लेकिन सिस्टम मेटा-डेटा उनके लिए ऐसा करने की अनुमति देता है - जो कि उन क्षेत्रों में से किसी की सबसे बड़ी अधिकतम लंबाई है - कम से कम गारंटी देता है कि भविष्य में आपके लिए या इस कोड को कॉपी करने वाले किसी अन्य व्यक्ति के लिए कोई समस्या नहीं होगी, जिनके सिस्टम में पहले से ही कुछ अक्षर मौजूद हो सकते हैं।NVARCHARVARCHARNVARCHAR(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;

मैंने कॉलम के अंतर्निहित प्रकार के बारे में जानकारी के लिए तीन कॉलम जोड़े हैं OptionValue

नमूना उत्पादन

यदि क्लाइंट sql_variantडेटा को संभाल नहीं सकता है , तो unpvt.OptionValueकॉलम पर अंतिम (शीर्ष स्तर) को उदा nvarchar(256)


4

ठीक है, तो मैंने देख लिया

sp_helptext [sys.databases]

तब टूट गया जहां से कॉलम आ रहे थे। साथ लोगों को Latin1_General_CI_AS_KS_WSमिलान सभी सिस्टम तालिका से आ रहे हैंsys.syspalvalues जो एक सामान्य लुकअप तालिका प्रतीत होता है (यह एक ऐसी प्रणाली तालिका है, तो आप इसे देखने के लिए में डीएसी के माध्यम से कनेक्ट करना होगा।)।

मेरा अनुमान है कि यह निर्धारित है Latin1_General_CI_AS_KS_WS किसी भी संभावित लुकअप मान को संभालने के लिए । मैं देख सकता हूं कि हालांकि यह कष्टप्रद होगा।

परिभाषा देखने का एक और तरीका (मूल रूप से एक टिप्पणी में मैक्स द्वारा प्रदान किया गया है) है:

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';`
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.