2010-04-07 15 views
14

कोई SQL XML फ़ाइल प्राप्त करने वाले डुप्लिकेट रिकॉर्ड्स को कैसे रोकें, मुझे एक दैनिक XML फ़ाइल प्राप्त होती है जिसमें हजारों रिकॉर्ड होते हैं, प्रत्येक व्यवसाय लेनदेन होता है जिसे मुझे रिपोर्टिंग और बिलिंग में उपयोग के लिए किसी आंतरिक डेटाबेस में स्टोर करने की आवश्यकता होती है । मैं इस धारणा के तहत था कि प्रत्येक दिन की फ़ाइल में केवल अनन्य रिकॉर्ड होते थे, लेकिन उन्होंने पाया है कि अद्वितीय की मेरी परिभाषा प्रदाता के समान नहीं है।कोई प्राथमिक कुंजी

वर्तमान डेटा जो इस डेटा को आयात करता है वह एक सी # .Net 3.5 कंसोल एप्लिकेशन है, यह ऐसा करता है कि SQL Server 2008 डेटाबेस तालिका में SqlBulkCopy का उपयोग कर जहां कॉलम एक्सएमएल रिकॉर्ड्स की संरचना से मेल खाते हैं। प्रत्येक रिकॉर्ड में केवल 100 से अधिक फ़ील्ड होते हैं, और डेटा में कोई प्राकृतिक कुंजी नहीं होती है, या ऐसे फ़ील्ड जो मैं एक समग्र कुंजी अंत के रूप में समझने के साथ आ सकता हूं, नल को अनुमति देने के लिए भी। वर्तमान में तालिका में कई अनुक्रमणिका हैं, लेकिन कोई प्राथमिक कुंजी नहीं है।

असल में पूरी पंक्ति को अद्वितीय होना आवश्यक है। यदि एक फ़ील्ड अलग है, तो यह सम्मिलित करने के लिए पर्याप्त मान्य है। मैंने पूरी पंक्ति का एमडी 5 हैश बनाने, डेटाबेस में डालने और एसकब्लूल्ककॉपी को पंक्ति डालने से रोकने के लिए बाधा का उपयोग करके देखा, लेकिन मुझे नहीं लगता कि एमडी 5 हैश को बल्ककॉपी ऑपरेशन में कैसे प्राप्त किया जाए और मैं नहीं हूं सुनिश्चित करें कि पूरा ऑपरेशन विफल हो जाएगा और यदि कोई रिकॉर्ड विफल हुआ है, या यदि यह जारी रहेगा तो वापस रोल करें।

फ़ाइल में बहुत बड़ी संख्या में रिकॉर्ड्स हैं, जो एक्सएमएल में पंक्ति से पंक्ति में जा रहे हैं, डेटाबेस के लिए सभी क्षेत्रों से मेल खाने वाले रिकॉर्ड के लिए पूछताछ करते हैं, और फिर डालने का निर्णय लेना वास्तव में एकमात्र तरीका है जिसे मैं कर सकता हूं इस। मैं बस उम्मीद कर रहा था कि आवेदन पूरी तरह से फिर से लिखना न पड़े, और थोक प्रतिलिपि ऑपरेशन बहुत तेज है।

क्या किसी को प्राथमिक कुंजी के बिना डुप्लिकेट पंक्तियों को रोकने के दौरान एसकब्लूल्ककॉपी का उपयोग करने का कोई तरीका पता है? या ऐसा करने के लिए एक अलग तरीके के लिए कोई सुझाव?

उत्तर

15

मैं डेटा को एक स्टेजिंग टेबल में अपलोड करता हूं, फिर अंतिम तालिका में प्रतिलिपि पर डुप्लिकेट के साथ सौदा करता हूं।

उदाहरण के लिए, यदि आप एक (गैर अद्वितीय) मचान मेज पर सूचकांक "कुंजी"

+1

इसके अतिरिक्त, थोक आयात (इसके तेज़) – CResults

+0

@CResults के बाद तक अपनी स्टेजिंग तालिका में इंडेक्स न जोड़ें: हाँ, उल्लेख किया जाना चाहिए कि ... – gbn

+1

ठीक है कि निश्चित रूप से समझ में आता है और इसे कार्यान्वित करना आसान है। धन्यवाद। – kscott

4

मैं एक अस्थायी तालिका में प्रतिलिपि बनाउंगा और उसके बाद डेटा को वास्तविक गंतव्य तालिका में धक्का दूंगा। इस तरह, आप डुप्लिकेट की जांच और संभाल करने के लिए SQL का उपयोग कर सकते हैं।

+0

हैश का उपयोग करने का विचार दिलचस्प है। कुंजी अस्थायी तालिका से बनाई जा सकती है (जहां आप नल को संभाल सकते हैं)। दूसरी तरफ, यदि आपके पास कुछ गैर-अद्वितीय इंडेक्स हैं, तो आप सभी मैचों में, अगर कोई हो, तो कॉलम के कुछ सबसेट में अद्वितीय या निकट-अद्वितीय होने की संभावना है, और विशिष्टता निर्धारित करने के लिए उनके माध्यम से चला सकते हैं। – SeaDrive

1

डेटा मात्रा क्या है से निपटने के लिए बना सकते हैं? आपके पास 2 विकल्प हैं जो मैं देख सकता हूं:

1: अपने IDataReader को लागू करके और डेटा पर कुछ हैश का उपयोग करके इसे स्रोत पर फ़िल्टर करें, और बस किसी भी डुप्लीकेट को छोड़कर ताकि वे कभी भी टीडीएस में पास न हो जाएं।

2: इसे डीबी में फ़िल्टर करें; सबसे सरल स्तर पर, मुझे लगता है कि आपके पास आयात के कई चरण हो सकते हैं - कच्चे, असंगत डेटा - और फिर DISTINCT डेटा को अपने वास्तविक तालिकाओं में कॉपी करें, शायद यदि आप चाहते हैं तो एक मध्यवर्ती तालिका का उपयोग कर। आप इनमें से कुछ के लिए CHECKSUM का उपयोग करना चाहते हैं, लेकिन यह निर्भर करता है।

0

और उस तालिका को ठीक करें। किसी भी तालिका को कभी भी एक अद्वितीय सूचकांक के बिना होना चाहिए, अधिमानतः पीके के रूप में। यहां तक ​​कि यदि आप एक सरोगेट कुंजी जोड़ते हैं क्योंकि कोई प्राकृतिक कुंजी नहीं है, तो आपको विशेष रूप से किसी विशेष रिकॉर्ड की पहचान करने में सक्षम होना चाहिए। अन्यथा आप पहले से मौजूद डुप्लिकेट से कैसे छुटकारा पायेंगे?

6

यह देखते हुए कि आप SQL 2008 का उपयोग कर रहे हैं, आपके पास अपने एप्लिकेशन को बदलने की आवश्यकता के बिना आसानी से समस्या को हल करने के लिए दो विकल्प हैं (यदि बिल्कुल)।

पहला संभावित समाधान पहली बार की तरह दूसरी तालिका बना रहा है लेकिन सरोगेट पहचान कुंजी के साथ और ignore_dup_key विकल्प का उपयोग करके एक विशिष्टता बाधा जोड़ दी गई है जो आपके लिए डुप्लिकेट को खत्म करने के सभी भारी उठाने के लिए करेगी।

यहाँ एक उदाहरण आप SSMS में चला सकते हैं देखने के लिए क्या हो रहा है है:

if object_id('tempdb..#test1') is not null drop table #test1; 
if object_id('tempdb..#test2') is not null drop table #test2; 
go 


-- example heap table with duplicate record 

create table #test1 
(
    col1 int 
    ,col2 varchar(50) 
    ,col3 char(3) 
); 
insert #test1(col1, col2, col3) 
values 
    (250, 'Joe''s IT Consulting and Bait Shop', null) 
    ,(120, 'Mary''s Dry Cleaning and Taxidermy', 'ACK') 
    ,(250, 'Joe''s IT Consulting and Bait Shop', null) -- dup record 
    ,(666, 'The Honest Politician', 'LIE') 
    ,(100, 'My Invisible Friend', 'WHO') 
; 
go 


-- secondary table for removing duplicates 

create table #test2 
(
    sk int not null identity primary key 
    ,col1 int 
    ,col2 varchar(50) 
    ,col3 char(3) 

    -- add a uniqueness constraint to filter dups 
    ,constraint UQ_test2 unique (col1, col2, col3) with (ignore_dup_key = on) 
); 
go 


-- insert all records from original table 
-- this should generate a warning if duplicate records were ignored 

insert #test2(col1, col2, col3) 
select col1, col2, col3 
from #test1; 
go 

या फिर, आप एक दूसरी तालिका के बिना यथा-स्थान डुप्लिकेट को हटा सकते हैं, लेकिन प्रदर्शन अपनी आवश्यकताओं के लिए बहुत धीमी गति से हो सकता है । यहाँ है कि उदाहरण के लिए कोड है, भी SSMS में runnable:

if object_id('tempdb..#test1') is not null drop table #test1; 
go 


-- example heap table with duplicate record 

create table #test1 
(
    col1 int 
    ,col2 varchar(50) 
    ,col3 char(3) 
); 
insert #test1(col1, col2, col3) 
values 
    (250, 'Joe''s IT Consulting and Bait Shop', null) 
    ,(120, 'Mary''s Dry Cleaning and Taxidermy', 'ACK') 
    ,(250, 'Joe''s IT Consulting and Bait Shop', null) -- dup record 
    ,(666, 'The Honest Politician', 'LIE') 
    ,(100, 'My Invisible Friend', 'WHO') 
; 
go 


-- add temporary PK and index 

alter table #test1 add sk int not null identity constraint PK_test1 primary key clustered; 
create index IX_test1 on #test1(col1, col2, col3); 
go 


-- note: rebuilding the indexes may or may not provide a performance benefit 

alter index PK_test1 on #test1 rebuild; 
alter index IX_test1 on #test1 rebuild; 
go 


-- remove duplicates 

with ranks as 
(
    select 
     sk 
     ,ordinal = row_number() over 
     ( 
      -- put all the columns composing uniqueness into the partition 
      partition by col1, col2, col3 
      order by sk 
     ) 
    from #test1 
) 
delete 
from ranks 
where ordinal > 1; 
go 


-- remove added columns 

drop index IX_test1 on #test1; 
alter table #test1 drop constraint PK_test1; 
alter table #test1 drop column sk; 
go 
1

मुझे लगता है कि यह एक बहुत क्लीनर है।

var dtcolumns = new string[] { "Col1", "Col2", "Col3"}; 

var dtDistinct = dt.DefaultView.ToTable(true, dtcolumns); 

using (SqlConnection cn = new SqlConnection(cn) 
{ 
       copy.ColumnMappings.Add(0, 0); 
       copy.ColumnMappings.Add(1, 1); 
       copy.ColumnMappings.Add(2, 2); 
       copy.DestinationTableName = "TableNameToMapTo"; 
       copy.WriteToServer(dtDistinct); 

} 

इस तरह से केवल एक डेटाबेस तालिका की आवश्यकता है और कोड में Bussiness Logic को रख सकते हैं।

0

बस का प्रयोग क्यों नहीं, एक प्राथमिक कुंजी के बजाय, एक सूचकांक बना सकते हैं और सेट

Ignore Duplicate Keys: YES 

यह होगा prevent any duplicate key to fire an error, और यह नहीं बनाया जाएगा (के रूप में यह पहले से मौजूद है)।

enter image description here

मैं इस विधि हर दिन लगभग 120.000 पंक्तियां सम्मिलित और दोषरहित काम करता है का उपयोग करें।

+0

क्या किसी सूचकांक में कितने फ़ील्ड शामिल किए जाने चाहिए इस पर कोई कठोर या व्यावहारिक सीमा है? प्रश्न में डेटा की प्रत्येक पंक्ति में 100 से अधिक फ़ील्ड हैं और प्रत्येक फ़ील्ड को इंडेक्स में होना आवश्यक है। क्या यह संसाधनों की अव्यवहारिक मात्रा का उपयोग नहीं करेगा? – kscott

+0

आपको यह समझने की जरूरत है कि 'इंडेक्स' क्या करता है और इसके लिए है, उदाहरण के लिए, यह 'दस्तावेज़ डुप्लिकेट कुंजी' को अनदेखा करना केवल 'document_id' पर लागू होना है और मेरी अन्य दो अनुक्रमणिका सहायक हैं, इसलिए खोज को और भी पुनर्प्राप्त किया जा सकता है जैसे ही मैं उन क्षेत्रों की खोज करता हूं, रिकॉर्ड्स की विशाल मात्रा में तेज़ी से ... लेकिन एक सीमा होनी चाहिए, हालांकि मुझे लगता है कि यह एक हार्डवेयर सीमा (सीपीयू + मेमोरी) है और डेटाबेस एक नहीं है ... – balexandre

संबंधित मुद्दे