ОШИБКА SQL: столбец уже привязан к DEFAULT

У меня есть таблица, как показано ниже, со столбцом значений по умолчанию как [IsProcessed]

IF NOT EXISTS (SELECT * FROM sys.objects 
               WHERE object_id = OBJECT_ID(N'[dbo].[Kovair_JileEventHistory]') 
                 AND type in (N'U'))
BEGIN
    CREATE TABLE [dbo].[Kovair_JileEventHistory]
    (
        [Id] [bigint] IDENTITY(1,1) NOT NULL,
        [GeneratedActionId] [char](36) NOT NULL,
        [BaseUrl] [nvarchar](255) NOT NULL,
        [ProjectName] [nvarchar](255) NOT NULL,
        [EntityName] [varchar](255) NOT NULL,
        [EntityId] [varchar](255) NOT NULL,
        [RelatedEntityName] [varchar](255) NOT NULL,
        [RelatedEntityId] [varchar](255) NOT NULL,
        [ActionName] [varchar](255) NOT NULL,
        [LoopbackEventName] [varchar](255) NOT NULL,
        [LastUpdatedOnGMT] [varchar](50) NOT NULL,
        [LastUpdatedBy] [nvarchar](255) NOT NULL,
        [IsProcessed] [char](1) NULL,

        PRIMARY KEY CLUSTERED ([Id] ASC)
                WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
                      IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                      ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
END

IF NOT EXISTS (SELECT * FROM sys.objects 
               WHERE object_id = OBJECT_ID(N'[dbo].[DF__Kovair_Ji__IsPro__5224328E]') 
                 AND type = 'D')
BEGIN
    ALTER TABLE [dbo].[Kovair_JileEventHistory] 
        ADD DEFAULT ('N') FOR [IsProcessed]
END

Когда я выполняю эти строки в другой системе, если я выполняю ее один раз, она работает нормально, но во второй раз, когда я выполняю ее, она дает мне ошибку, как показано ниже.

Msg 1781, Level 16, State 1, Line 26
Column already has a DEFAULT bound to it.

Msg 1750, Level 16, State 0, Line 26
Could not create constraint. See previous errors.

Но когда я делаю то же самое в своей системе, из которой я сгенерировал этот скрипт, я могу выполнить его несколько раз без каких-либо ошибок.

Я думаю

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[DF__Kovair_Ji__IsPro__5224328E]') AND type = 'D')
BEGIN
ALTER TABLE [dbo].[Kovair_JileEventHistory] ADD  DEFAULT ('N') FOR [IsProcessed]
END

в этой строке часть, где OBJECT_ID(N'[dbo].[DF__Kovair_Ji__IsPro__5224328E]') зависит от системы.

Есть ли способ решить эту проблему?

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
0
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это ошибочно:

IF NOT EXISTS 
(
  SELECT * FROM sys.objects 
  WHERE object_id = OBJECT_ID(N'[dbo].[DF__Kovair_Ji__IsPro__5224328E]') 
  AND type = 'D'
)

По нескольким причинам:

  1. Вы позволяете системе назвать ограничение, что означает, что каждый раз, когда вы создаете таблицу, эта система будет придумывать новое имя. Вы всегда должны явно называть свои ограничения, чтобы такие сценарии можно было сделать более предсказуемыми и чтобы у вас было разумное соглашение об именах.

     ALTER TABLE dbo.tablename 
       ADD CONSTRAINT DF_SomethingSmarter
       DEFAULT('N') FOR IsProcessed;
    
  2. Вы в основном просто говорите: «Есть ли ограничение по умолчанию для этой таблицы с этим именем», но вы жестко закодировали имя ограничения. Возможно, это может вести себя по-другому в системе другой по другой причине — скажем, есть еще один столбец, начинающийся с IsPro..., и это бывает, чтобы получить псевдослучайное имя ограничения, сгенерированное системой такой же.

  3. Если вы знаете, какой столбец и какой тип ограничения, гораздо более безопасная (и, по общему признанию, более подробная) проверка состоит в том, чтобы игнорировать имя ограничения и идти после имени таблицы + столбца:

     IF NOT EXISTS 
     (
       SELECT 1 FROM sys.default_constraints AS dc
        WHERE parent_object_id = OBJECT_ID(N'dbo.Kovair_JileEventHistory')
        AND EXISTS
        (
           SELECT 1 FROM sys.columns AS c 
            WHERE c.object_id = dc.parent_object_id
              AND c.column_id = dc.parent_column_id
              AND c.name = N'IsProcessed')
        )
     )
     BEGIN
       -- now I know there is no default constraint
       -- on this column, no matter what it's named
     END
    

    Я бы даже предложил что-то более подробное, поскольку в масштабе некоторые функции метаданных не подчиняются семантике изоляции, что может быть проблематично в зависимости от области изменения и возможности восстановления всего скрипта:

     IF NOT EXISTS 
     (
       SELECT 1 FROM sys.default_constraints AS dc
        INNER JOIN sys.tables AS t
          ON t.[object_id] = dc.parent_object_id
          AND t.name = N'Kovair_JileEventHistory'
          AND t.[schema_id] = 1
        WHERE EXISTS
        ...
    

Другие вопросы по теме