2011-08-04 8 views
11

मैं एमएस एसक्यूएल सर्वर का उपयोग करता हूं।यह पता लगाने के लिए कि किसी तालिका में कुछ अद्वितीय कॉलम हैं

Ive उन पर कोई बाधा नहीं के साथ कुछ बड़ी टेबल सौंपी गई, कोई चाबियाँ कुछ भी नहीं।

मुझे पता है कि कुछ स्तंभों में अद्वितीय मान हैं। क्या किसी दिए गए टेबल के लिए अद्वितीय मूल्य वाले कोल्स ढूंढने का कोई स्मार्ट तरीका है?

अभी मैं प्रत्येक कॉलम के लिए इसे मैन्युअल रूप से कर रहा हूं, यदि तालिका में पंक्तियों के रूप में कई DISTINCT मान हैं।

SELECT COUNT(DISTINCT col) FROM table 

सभी स्तंभों पर पाश करने के लिए एक cusor बनाने समस्या है, लेकिन अगर किसी को एक होशियार जानता है या निर्माण में समारोह सुनना चाहते हो सका।

धन्यवाद।

उत्तर

8

यहाँ एक दृष्टिकोण है कि मूल रूप से @ JNK के लिए इसी तरह की, लेकिन इसके बजाय मायने रखता है यह हर स्तंभ है जो आपको बताता के लिए एक तैयार जवाब देता है मुद्रण की है एक कॉलम केवल या नहीं अनन्य मानों के होते हैं या नहीं:

DECLARE @table varchar(100), @sql varchar(max); 
SET @table = 'some table name'; 

SELECT 
    @sql = COALESCE(@sql + ', ', '') + ColumnExpression 
FROM (
    SELECT 
    ColumnExpression = 
     'CASE COUNT(DISTINCT ' + COLUMN_NAME + ') ' + 
     'WHEN COUNT(*) THEN ''UNIQUE'' ' + 
     'ELSE '''' ' + 
     'END AS ' + COLUMN_NAME 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = @table 
) s 

SET @sql = 'SELECT ' + @sql + ' FROM ' + @table; 
PRINT @sql; /* in case you want to have a look at the resulting query */ 
EXEC(@sql); 

यह प्रत्येक कॉलम के लिए COUNT(*) के साथ COUNT(DISTINCT column) की तुलना करता है। परिणाम एक पंक्ति के साथ एक तालिका होगी, जहां प्रत्येक कॉलम में उन कॉलम के लिए UNIQUE मान होगा जिसमें डुप्लिकेट नहीं होंगे, और डुप्लीकेट मौजूद होने पर खाली स्ट्रिंग होगी।

लेकिन उपर्युक्त समाधान केवल उन स्तंभों के लिए सही ढंग से काम करेगा जिनके पास न्यूल नहीं है।यह ध्यान दिया जाना चाहिए कि जब आप कॉलम पर एक अद्वितीय बाधा/अनुक्रमणिका बनाना चाहते हैं तो SQL सर्वर NULL को अनदेखा नहीं करता है। यदि किसी कॉलम में केवल एक नल होता है और अन्य सभी मान अनूठे होते हैं, तो आप अभी भी कॉलम पर एक अनूठी बाधा बना सकते हैं (आप इसे प्राथमिक कुंजी नहीं बना सकते हैं, हालांकि, मूल्यों की असीमितता और एनयूएलएल की अनुपस्थिति दोनों की आवश्यकता होती है)।

इसलिए आप सामग्री है, जिसे आप निम्न स्क्रिप्ट के साथ मिल सकता है की एक और अधिक गहन विश्लेषण की आवश्यकता हो सकती: COUNT(DISTINCT column), COUNT(column) और COUNT(*):

DECLARE @table varchar(100), @sql varchar(max); 
SET @table = 'some table name'; 

SELECT 
    @sql = COALESCE(@sql + ', ', '') + ColumnExpression 
FROM (
    SELECT 
    ColumnExpression = 
     'CASE COUNT(DISTINCT ' + COLUMN_NAME + ') ' + 
     'WHEN COUNT(*) THEN ''UNIQUE'' ' + 
     'WHEN COUNT(*) - 1 THEN ' + 
     'CASE COUNT(DISTINCT ' + COLUMN_NAME + ') ' + 
     'WHEN COUNT(' + COLUMN_NAME + ') THEN ''UNIQUE WITH SINGLE NULL'' ' + 
     'ELSE '''' ' + 
     'END ' + 
     'WHEN COUNT(' + COLUMN_NAME + ') THEN ''UNIQUE with NULLs'' ' + 
     'ELSE '''' ' + 
     'END AS ' + COLUMN_NAME 
    FROM INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = @table 
) s 

SET @sql = 'SELECT ' + @sql + ' FROM ' + @table; 
PRINT @sql; /* in case you still want to have a look at the resulting query */ 
EXEC(@sql); 

यह समाधान तीन मानों की जाँच करके खाते में NULLs लेता है। यह पूर्व समाधान की तरह ही परिणाम प्रदर्शित करता है, लेकिन स्तंभों के लिए संभव निदान अधिक विविधता होती है:

  • UNIQUE मतलब है कि कोई डुप्लिकेट मानों और कोई NULLs (या तो पी है या एक अनूठा बाधा/सूचकांक हो सकते हैं) ;

  • UNIQUE WITH SINGLE NULL - अनुमान लगाया जा सकता है, कोई डुप्लीकेट नहीं है, लेकिन एक नल है (पीके नहीं हो सकता है, लेकिन एक अद्वितीय बाधा/सूचकांक हो सकता है);

  • UNIQUE with NULLs - कोई डुप्लीकेट नहीं, दो या अधिक NULLs (यदि आप SQL Server 2008 पर हैं, तो आपके पास केवल गैर-नल मानों के लिए एक सशर्त अद्वितीय अनुक्रमणिका हो सकती है);

  • खाली स्ट्रिंग - डुप्लिकेट हैं, संभवतः एनयूएलएल भी हैं।

+0

त्रुटि दे रहा है "चेतावनी: कुल मूल्य एक कुल या अन्य एसईटी ऑपरेशन द्वारा समाप्त किया गया है।" आवेदन से उपयोग नहीं किया जा सकता है। – ratneshsinghparihar

+0

@ user998660: "आवेदन से विशेष रूप से चेतावनियों के प्रति संवेदनशील", आपका मतलब है? उस मामले में, नहीं, यह निश्चित रूप से नहीं कर सकता है। सभी अनुप्रयोग * * संवेदनशील नहीं हैं, हालांकि। उदाहरण के लिए, मुझे कभी भी ऐसी चेतावनियां उत्पन्न करने वाले समेकन वाले डेल्फी में समस्याएं याद नहीं हैं। वैसे भी, मेरी धारणा यह थी कि ओपी एक समाधान चाहता था जिसे वे "मैन्युअल रूप से" उपयोग कर सकते थे, उदाहरण के लिए, किसी प्रश्न के मामले में, इसे एसएसएमएस जैसे टूल में आमंत्रित करना। –

1

यदि आप 2008 का उपयोग कर रहे हैं, तो आप प्रत्येक तालिका के लिए उम्मीदवार कुंजी वापस करने के लिए एसएसआईएस में डेटा प्रोफाइलिंग कार्य का उपयोग कर सकते हैं।

प्रक्रिया के माध्यम से इस ब्लॉग प्रविष्टि कदम, यह काफी सरल है:

http://consultingblogs.emc.com/jamiethomson/archive/2008/03/04/ssis-data-profiling-task-part-8-candidate-key.aspx

+0

बहुत जानकारीपूर्ण टूल - संकेत के लिए धन्यवाद – zmaster

1

में कुछ शब्द मेरे कोड है:

  1. पढ़ें के सभी तालिकाओं और स्तंभों

  2. डुप्लिकेट कुंजियों के साथ तालिका/कॉलम रखने के लिए एक अस्थायी तालिका बनाता है

  3. प्रत्येक तालिका/कॉलम के लिए यह एक क्वेरी चलाता है। यदि इसे कम से कम एक मान के लिए गिनती (*)> 1 मिलती है तो यह अस्थायी तालिका

  4. सिस्टम टेबल से कॉलम और मान चुनें जो डुप्लिकेट वाले तालिका/कॉलम से मेल नहीं खाते हैं

    DECLARE @sql VARCHAR(max) 
    DECLARE @table VARCHAR(100) 
    DECLARE @column VARCHAR(100) 
    
    
    CREATE TABLE #temp (tname VARCHAR(100),cname VARCHAR(100)) 
    
    DECLARE mycursor CURSOR FOR 
    select t.name,c.name 
    from sys.tables t 
    join sys.columns c on t.object_id = c.object_id 
    where system_type_id not in (34,35,99) 
    
    OPEN mycursor 
    FETCH NEXT FROM mycursor INTO @table,@column 
    
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
    SET @sql = 'INSERT INTO #temp SELECT DISTINCT '''[email protected]+''','''[email protected]+ ''' FROM ' + @table + ' GROUP BY ' + @column +' HAVING COUNT(*)>1 ' 
    EXEC (@sql) 
    FETCH NEXT FROM mycursor INTO @table,@column 
    END 
    
    select t.name,c.name 
    from sys.tables t 
    join sys.columns c on t.object_id = c.object_id 
    left join #temp on t.name = #temp.tname and c.name = #temp.cname 
    where system_type_id not in (34,35,99) and #temp.tname IS NULL 
    
    DROP TABLE #temp 
    
    CLOSE mycursor 
    DEALLOCATE mycursor 
    
+0

आपके उत्तर के लिए धन्यवाद, मैंने यह कोशिश नहीं की है क्योंकि यह सभी सारणीओं पर चलता है जो मुझे इस विशिष्ट प्रश्न के लिए आवश्यक नहीं है। – zmaster

+0

आप कर्सर क्वेरी परिभाषा में एक अतिरिक्त खंड डाल सकते हैं: और tname = your_table_name – niktrs

2

यहाँ मैं शायद स्पष्ट तरीका लगता है। केवल एक क्वेरी बनाने के लिए गतिशील एसक्यूएल और एक एकल चयन कथन का उपयोग करें जो आपको कुल पंक्ति गणना और प्रत्येक फ़ील्ड के लिए अलग-अलग मानों की गिनती देता है।

शीर्ष पर डीबी नाम और टैबलेट नाम भरें। OBJECT_NAME केवल वर्तमान डेटाबेस संदर्भ में काम करता है क्योंकि डीबी नाम भाग वास्तव में महत्वपूर्ण है।

use DatabaseName 

DECLARE @Table varchar(100) = 'TableName' 

DECLARE @SQL Varchar(max) 

SET @SQL = 'SELECT COUNT(*) as ''Total''' 

SELECT @SQL = @SQL + ',COUNT(DISTINCT ' + name + ') as ''' + name + '''' 
FROM sys.columns c 
WHERE OBJECT_NAME(object_id) = @Table 

SET @SQL = @SQL + ' FROM ' + @Table 

exec @sql 
+1

कॉलम में कोई एनयूएलएल नहीं होने पर यह बहुत उपयोगी होगा। अद्वितीय बाधाओं/इंडेक्स बनाने के दौरान SQL सर्वर में एनयूएलएल को ध्यान में रखा जाता है। –

0

कोड के सरल एक पंक्ति के बारे में क्या:

CREATE UNIQUE INDEX index_name ON table_name (column_name); 

तो सूचकांक तो बनाई गई है अपने स्तंभ केवल अनन्य मान हैं। यदि आपके कॉलम_नाम में डुप्लीस हैं, तो आपको एक त्रुटि संदेश मिलेगा।