2008-11-06 11 views
19

है, मैं एक तालिका में रिकॉर्ड डालने का सबसे अच्छा तरीका जानने की कोशिश कर रहा हूं, लेकिन केवल तभी आइटम मौजूद नहीं है। इस मामले में कुंजी एक NVARCHAR (400) क्षेत्र है। इस उदाहरण के लिए, ऑक्सफोर्ड अंग्रेजी शब्दकोश में शब्द का नाम दें/यहां अपना एफएवी शब्दकोश डालें। साथ ही, मुझे लगता है कि मुझे वर्ड फ़ील्ड को प्राथमिक कुंजी बनाने की आवश्यकता होगी। (तालिका में एक अद्वितीय पहचानकर्ता पीके भी होगा)।एसक्यूएल सर्वर - रिकॉर्ड कैसे सम्मिलित करें और सुनिश्चित करें कि यह अद्वितीय

तो .. मैं इन शब्दों है कि मैं मेज पर जोड़ने की जरूरत है ...

जैसे मिल सकता है।

  • बिल्ली
  • कुत्ता
  • फू
  • बार
  • PewPew
  • आदि ...

तो पारंपरिक रूप से, मैं निम्नलिखित (छद्म कोड) की कोशिश करेगा

SELECT WordID FROM Words WHERE Word = @Word 
IF WordID IS NULL OR WordID <= 0 
    INSERT INTO Words VALUES (@Word) 

यानी। यदि शब्द मौजूद नहीं है, तो उसे डालें।

अब .. जिस समस्या के बारे में मुझे चिंता है, वह है कि हमें हिट्स के बहुत सारे मिल रहे हैं .. तो क्या यह संभव है कि शब्द को चयन और INSERT के बीच में किसी अन्य प्रक्रिया से डाला जा सके .. जो होगा फिर एक बाधा त्रुटि फेंक दें? (यानी Race Condition)।

मैं तो सोचा था कि मैं निम्न करने के लिए सक्षम हो सकता है ...

INSERT INTO Words (Word) 
SELECT @Word 
WHERE NOT EXISTS (SELECT WordID FROM Words WHERE Word = @Word) 

मूल रूप से, जब यह अस्तित्व में नहीं है एक शब्द डालते हैं।

खराब वाक्यविन्यास एक तरफ, मुझे यकीन नहीं है कि यह तालिका के नीचे ताले होने के कारण खराब या अच्छा है (यदि यह करता है) और वह उस टेबल पर प्रदर्शन करने वाला नहीं है जो इसे बड़े पैमाने पर पढ़ता है और बहुत सारे लिखते हैं ।

तो - आप एसक्यूएल गुरु क्या सोचते हैं/करते हैं?

मैं एक साधारण डालने और 'पकड़' की उम्मीद कर रहा था कि किसी भी त्रुटि को फेंक दिया जाए।

उत्तर

24

आपका समाधान:

INSERT INTO Words (Word) 
    SELECT @Word 
WHERE NOT EXISTS (SELECT WordID FROM Words WHERE Word = @Word) 

... के रूप में यह हो जाता है के बारे में के रूप में अच्छा है। आप इस के लिए यह आसान बनाने सकता है:

INSERT INTO Words (Word) 
    SELECT @Word 
WHERE NOT EXISTS (SELECT * FROM Words WHERE Word = @Word) 

... वजह से मौजूद है वास्तव में किसी भी रिकॉर्ड वापस जाने के लिए की जरूरत नहीं है, तो क्वेरी अनुकूलक, जिस पर फ़ील्ड के लिए कहा की तलाश में परेशान नहीं करेगा।

जैसा कि आप उल्लेख करते हैं, हालांकि, यह विशेष रूप से निष्पादक नहीं है, क्योंकि यह INSERT के दौरान पूरी तालिका को लॉक कर देगा। इसके अलावा, यदि आप वर्ड में एक अनन्य अनुक्रमणिका (इसे प्राथमिक कुंजी होने की आवश्यकता नहीं है) जोड़ते हैं, तो उसे केवल प्रासंगिक पृष्ठों को लॉक करने की आवश्यकता होगी।

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

यदि यह अभी भी आपको पर्याप्त प्रदर्शन नहीं दे रहा है, तो डेटा वेयरहाउसिंग क्षेत्र से तकनीकों का एक समूह है जो मदद कर सकता है।

CREATE UNIQUE [ CLUSTERED | NONCLUSTERED ] INDEX <index_name> 
    ON Words (word [ ASC | DESC ]) 

निर्दिष्ट Clustered या NonClustered, आपके मामले के आधार पर:

+1

क्या EXISTS (चयन * से ...) और EXISTS (से चुनें 1 ...) के बीच कोई प्रदर्शन अंतर है? स्टार से बचने के लिए मैं हमेशा बाद वाले का उपयोग करता हूं - क्या वह फायदेमंद है या यह सब वही है? – Tomalak

+0

मुझे संदेह है कि यह वही है, लेकिन आपको यह सुनिश्चित करने के लिए SQL सर्वर प्रोफाइलर में इसे आग लगाना होगा। –

+0

मैं भी अपने चयन में * कभी नहीं *, लेकिन हमेशा वापसी फ़ील्ड/मान निर्दिष्ट करता हूं। –

3

आप एमएस एसक्यूएल सर्वर का उपयोग कर रहे हैं, तो आप अपनी तालिका के स्तंभों अद्वितीय होने चाहिए कि पर एक अद्वितीय सूचकांक (दस्तावेज here) बना सकते हैं। साथ ही, यदि आप इसे सॉर्ट करना चाहते हैं (तेज़ी से खोजना सक्षम करने के लिए), सॉर्ट ऑर्डर के लिए ASC या DESC निर्दिष्ट करें।

here देखें, यदि आप इंडेक्स आर्किटेक्चर के बारे में अधिक जानना चाहते हैं।

अन्यथा, आप दस्तावेज here तरह UNIQUE CONSTRAINTS इस्तेमाल कर सकते हैं:

ALTER TABLE Words 
ADD CONSTRAINT UniqueWord 
UNIQUE (Word); 
0

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

एक बार फिर, मैं अस्वीकार करता हूं कि यह सब मेरे ज्ञान से MySQL प्रोग्रामिंग और मेरे डेटाबेस वर्ग से है, इसलिए माफी एसक्यूएल की जटिलताओं पर मैं क्षमा चाहता हूं।

1

जबकि अद्वितीय बाधा certaily एक तरह से आप भी अपने डालने तर्क के लिए इसका उपयोग कर सकते जाने के लिए है: http://www.sqlteam.com/article/application-locks-or-mutexes-in-sql-server-2005

मूल रूप से आप इस प्रकार के बारे में चिंता नहीं नीचे दी गई तालिका पर कोई ताले डाल नहीं पढ़ता है, जबकि अपनी अस्तित्व जांच ठीक से किया जाएगा।

यह एसक्यूएल कोड में एक म्यूटेक्स है।

-1
declare @Error int 

begin transaction 
    INSERT INTO Words (Word) values(@word) 
    set @Error = @@ERROR 
    if @Error <> 0 --if error is raised 
    begin 
     goto LogError 
    end 
commit transaction 
goto ProcEnd 

LogError: 
rollback transaction 
+0

दोस्त - मैंने अपनी शुरुआती पोस्ट में कहा कि मैं एक गूंगा सम्मिलित नहीं करना चाहता था और फिर त्रुटियों की जांच करता हूं। यह बहुत स्मार्ट आईएमओ नहीं है। –

2

मैं इसी तरह की समस्या थी और यह मैं कैसे हल यह

insert into Words 
(selectWord , Fixword) 
SELECT word,'theFixword' 
FROM OldWordsTable 
WHERE 
(
    (word LIKE 'junk%') OR 
    (word LIKE 'orSomthing') 

) 
and word not in 
    (
     SELECT selectWord FROM words WHERE selectWord = word 
    ) 
4

मुझे लगता है कि मैं एक बेहतर (या कम से कम तेजी से) इसका जवाब मिल गया है है।

CREATE UNIQUE NONCLUSTERED INDEX [IndexTableUniqueRows] ON [dbo].[table] 
(
    [Col1] ASC, 
    [Col2] ASC, 

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = ON, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 

सभी स्तंभों कि विशिष्टता को परिभाषित शामिल करें: की तरह एक सूचकांक बनाएँ। महत्वपूर्ण हिस्सा IGNORE_DUP_KEY = चालू है। यह चेतावनियों में गैर अद्वितीय आवेषण बदल जाता है। एसएसआईएस इन चेतावनियों को अनदेखा करता है और आप अभी भी फास्टलोड का उपयोग कर सकते हैं।

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