سؤال

أحاول اكتشاف أفضل طريقة لإدراج سجل في جدول واحد ولكن فقط إذا لم يكن العنصر موجودًا بالفعل.المفتاح في هذه الحالة هو حقل NVARCHAR(400).في هذا المثال، دعونا نتظاهر بأنه اسم كلمة في قاموس أوكسفورد الإنجليزي / أدخل قاموسك المفضل هنا.أعتقد أيضًا أنني سأحتاج إلى جعل حقل Word مفتاحًا أساسيًا.(سيحتوي الجدول أيضًا على معرف فريد PK أيضًا).

لذا ..قد أحصل على هذه الكلمات التي أحتاج إلى إضافتها إلى الجدول ...

على سبيل المثال.

  • قطة
  • كلب
  • فو
  • حاجِز
  • بيو بيو
  • إلخ...

تقليديًا، سأحاول ما يلي (الرمز الزائف)

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

أي. إذا كانت الكلمة غير موجودة، قم بإدراجها.

الآن ..المشكلة التي أشعر بالقلق بشأنها هي أننا نتلقى الكثير من الزيارات ..فهل من الممكن إدراج الكلمة من عملية أخرى بين SELECT و INSERT ..والذي من شأنه أن يلقي خطأ القيد؟(أي.أ حالة السباق).

ثم اعتقدت أنني قد أكون قادرًا على القيام بما يلي ...

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

أساسًا، أدخل كلمة عندما لا تكون موجودة.

بغض النظر عن بناء الجملة السيئ، لست متأكدًا مما إذا كان هذا سيئًا أم جيدًا نظرًا لكيفية قفل الجدول (إذا كان كذلك) وليس هذا الأداء على الطاولة بحيث يحصل على قراءات هائلة والكثير من عمليات الكتابة.

إذًا - ما هو رأي/فعل معلمو Sql؟

كنت أتمنى أن أحصل على إدراج بسيط و"التقاط" أي أخطاء يتم إلقاؤها.

هل كانت مفيدة؟

المحلول

الحل الخاص بك:

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)

...لأن EXISTS لا يحتاج فعليًا إلى إرجاع أي سجلات، لذا فإن مُحسِّن الاستعلام لن يكلف نفسه عناء البحث في الحقول التي طلبتها.

ومع ذلك، كما ذكرت، فإن هذا ليس ذا أداء خاص، لأنه سيقفل الجدول بأكمله أثناء عملية الإدراج.باستثناء ذلك، إذا قمت بإضافة فهرس فريد (لا يلزم أن يكون المفتاح الأساسي) إلى Word، فسوف يحتاج فقط إلى قفل الصفحات ذات الصلة.

أفضل خيار لديك هو محاكاة التحميل المتوقع وإلقاء نظرة على الأداء باستخدام SQL Server Profiler.كما هو الحال مع أي مجال آخر، يعد التحسين المبكر أمرًا سيئًا.حدد مقاييس الأداء المقبولة، ثم قم بالقياس قبل القيام بأي شيء آخر.

إذا كان هذا لا يزال لا يمنحك الأداء المناسب، فهناك مجموعة من التقنيات من مجال تخزين البيانات التي يمكن أن تساعدك.

نصائح أخرى

أعتقد أنني وجدت إجابة أفضل (أو على الأقل أسرع) لهذا السؤال.قم بإنشاء فهرس مثل:

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 = ON.يؤدي ذلك إلى تحويل الإدخالات غير الفريدة إلى تحذيرات.يتجاهل SSIS هذه التحذيرات ولا يزال بإمكانك استخدام التحميل السريع أيضًا.

إذا كنت تستخدم MS SQL Server، فيمكنك إنشاء فهرس فريد على أعمدة الجدول الخاص بك والتي يجب أن تكون فريدة (موثقة هنا):

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

تحديد Clustered أو NonClustered, ، حسب حالتك.أيضًا، إذا كنت تريد فرزها (لتمكين البحث بشكل أسرع)، فحدد ASC أو DESC لترتيب الفرز.

يرى هنا, ، إذا كنت تريد معرفة المزيد عن بنية الفهارس.

خلاف ذلك، يمكنك استخدام UNIQUE CONSTRAINTS مثل موثقة هنا:

ALTER TABLE Words
ADD CONSTRAINT UniqueWord
UNIQUE (Word); 

واجهت مشكلة مماثلة وهذه هي الطريقة التي قمت بحلها

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
    ) 

في حين أن القيد الفريد هو بالتأكيد إحدى الطرق للذهاب، يمكنك أيضًا استخدام هذا لمنطق الإدراج الخاص بك:http://www.sqlteam.com/article/application-locks-or-mutexes-in-sql-server-2005

بشكل أساسي ، لا تضع أي أقفال على الطاولة أدناه وبالتالي لا تقلق بشأن القراءات بينما سيتم إجراء فحوصات الوجود الخاصة بك بشكل جيد.

إنه كائن المزامنة (mutex) في كود SQL.

لا أستطيع التحدث عن تفاصيل MS SQL، ولكن هناك نقطة واحدة للمفتاح الأساسي في SQL وهي ضمان التفرد.لذا، وفقًا للتعريف في مصطلحات SQL العامة، فإن المفتاح الأساسي هو حقل واحد أو أكثر فريد للجدول.على الرغم من وجود طرق مختلفة لفرض هذا السلوك (استبدل الإدخال القديم بالإدخال الجديد مقابل الإدخال الجديد).رفض الجديد) سأفاجأ إذا لم يكن لدى MS SQL آلية لفرض هذا السلوك وأنه لم يكن لرفض الإدخال الجديد.فقط تأكد من تعيين المفتاح الأساسي لحقل Word و يجب عمل.

ومع ذلك، مرة أخرى، فإنني أنكر أن هذا كله من معرفتي ببرمجة MySQL وفئة قواعد البيانات الخاصة بي، لذا أعتذر إذا لم أتمكن من التعامل مع تعقيدات MS SQL.

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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top