سؤال

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

CREATE TRIGGER [dbo].[BeforeUpdateUser]
   ON  [dbo].[Users]
   INSTEAD OF INSERT
AS 
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @Email nvarchar(MAX)
    DECLARE @UserName nvarchar(MAX)
    DECLARE @UserId int
    DECLARE @DoInsert bit

    SET @DoInsert = 1

    SELECT @Email = Email, @UserName = UserName FROM INSERTED

    SELECT @UserId = UserId FROM Users WHERE Email = @Email

    IF (@UserId IS NOT NULL)
        BEGIN
            SET @DoInsert = 0
        END

    SELECT @UserId = UserId FROM Users WHERE UserName = @UserName

    IF (@UserId IS NOT NULL)
        BEGIN
            SET @DoInsert = 0
        END

    IF (@DoInsert = 1)
        BEGIN
            INSERT INTO Users
            SELECT 
                           FirstName, 
                           LastName, 
                           Email, 
                           Password, 
                           UserName, 
                           LanguageId,
                           Data, 
                           IsDeleted 
                       FROM INSERTED
        END
    ELSE
        BEGIN
            DECLARE @ErrorMessage nvarchar(MAX)
            SET @ErrorMessage = 
                         'The username and emailadress of a user must be unique!'
            RAISERROR 50001 @ErrorMessage
        END 
END

ولكن لتحديث التحديث ليس لدي أي فكرة عن كيفية القيام بذلك. لقد وجدت هذا المثال مع Google:http://www.devarticles.com/c/a/sql-server/using-triggers-in-ms-sql-server/2/لكنني لا أعرف إذا كان ينطبق عند تحديث أعمدة متعددة في وقت واحد.

تعديل:

لقد حاولت إضافة قيود فريدة على هذه الأعمدة، لكنها لا تعمل:

Msg 1919, Level 16, State 1, Line 1
Column 'Email' in table 'Users' is of a type 
that is invalid for use as a key column in an index.
هل كانت مفيدة؟

المحلول

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

ALTER TABLE [Users] ADD  CONSTRAINT [IX_UniqueUserEmail] UNIQUE NONCLUSTERED 
(
    [Email] ASC
)

ALTER TABLE [Users] ADD  CONSTRAINT [IX_UniqueUserName] UNIQUE NONCLUSTERED 
(
    [UserName] ASC
)

تحرير: حسنا، لقد قرأت تعليقاتك فقط إلى منشور آخر ورأيت أنك تستخدم NVARCHAR (MAX) كوعي بياناتك. هل هناك سبب لماذا قد ترغب في أكثر من 4000 حرفا لعنوان بريد إلكتروني أو اسم مستخدم؟ هذا هو المكان الذي تكمن مشكلتك. إذا قمت بتقليل هذا إلى NVARCHAR (250) أو ما بعد ذلك، يمكنك استخدام فهرس فريد.

نصائح أخرى

يبدو وكأنه الكثير من العمل بدلا من مجرد استخدام فهارس واحدة أو أكثر فريدة. هل هناك سبب لم تخطئ مسار الفهرس؟

لماذا لا تستخدم السمة الفريدة فقط في العمود في قاعدة البيانات الخاصة بك؟ الإعداد الذي سيجعل خادم SQL يفرض ذلك ورمي خطأ إذا حاولت إدراج Dupe.

يجب عليك استخدام SQL UNIQUE قيد على كل من هذه الأعمدة لذلك.

يمكنك إنشاء UNIQUE INDEX على NVARCHAR بمجرد أن يكون NVARCHAR(450) او اقل.

هل تحتاج حقا UNIQUE العمود ليكون كبير جدا؟

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

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

كن على دراية أنه إذا كنت تستخدم حل القيد / الفهرس الفريد مع SQL Server، فسيتم السماح بالقيمة الفاتورة فقط في هذا العمود. لذلك، على سبيل المثال، إذا كنت ترغب في أن يكون عنوان البريد الإلكتروني اختياريا، فلن يعمل ذلك، لأن مستخدم واحد فقط قد يكون له عنوان بريد إلكتروني فارغا. في هذه الحالة، يجب عليك اللجوء إلى نهج آخر مثل الزناد أو الفهرس المصفى.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top