как использовать параметризованную функцию для привязки по умолчанию для столбца Sql Server - PullRequest
1 голос
/ 27 марта 2010

У меня есть таблица, которая каталогизирует выбранные файлы из нескольких источников. Я хочу записать, является ли файл дубликатом ранее каталогизированного файла во время каталогизации нового файла. В моей таблице есть столбец («primary_duplicate») для записи каждой записи как «P» (основной) или «D» (дубликат). Я хотел бы предоставить привязку по умолчанию для этого столбца, которая будет проверять другие вхождения этого файла (например, имя, длина, метка времени) во время записи нового файла.

Я создал функцию, которая выполняет эту проверку (см. «GetPrimaryDuplicate» ниже). Но я не знаю, как связать эту функцию, для которой требуются три параметра, в столбец «primary_duplicate» таблицы в качестве привязки по умолчанию.

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

Как я могу вызвать эту функцию со значениями из вставляемой строки?

USE [MyDatabase]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[FileCatalog](
    [id] [uniqueidentifier] NOT NULL,
    [catalog_timestamp] [datetime] NOT NULL,
    [primary_duplicate] [nchar](1) NOT NULL,
    [name] [nvarchar](255) NULL,
    [length] [bigint] NULL,
    [timestamp] [datetime] NULL
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[FileCatalog] ADD  CONSTRAINT [DF_FileCatalog_id]  DEFAULT (newid()) FOR [id]
GO

ALTER TABLE [dbo].[FileCatalog] ADD  CONSTRAINT [DF_FileCatalog_catalog_timestamp]  DEFAULT (getdate()) FOR [catalog_timestamp]
GO

ALTER TABLE [dbo].[FileCatalog] ADD  CONSTRAINT [DF_FileCatalog_primary_duplicate]  DEFAULT (N'GetPrimaryDuplicate(name, length, timestamp)') FOR [primary_duplicate]
GO


USE [MyDatabase]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[GetPrimaryDuplicate] 
(
    @name nvarchar(255),
    @length bigint,
    @timestamp datetime
)
RETURNS nchar(1)
AS 
BEGIN

    DECLARE @c int

    SELECT @c = COUNT(*)
    FROM FileCatalog
    WHERE name=@name and length=@length and timestamp=@timestamp and primary_duplicate = 'P'

    IF @c > 0
        RETURN 'D' -- Duplicate

    RETURN 'P' -- Primary

END

GO

Ответы [ 3 ]

2 голосов
/ 25 октября 2010

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

Если это невозможно, вы могли бы сказать: «Это невозможно, поэтому вы должны вместо этого использовать триггер», чтобы он действительно мог чему-то научиться. Я уверен, что он так же хорошо, как и вы, знает, что такое триггеры и для чего они могут быть использованы.

ОП: Извините, но я ищу ту же информацию.

2 голосов
/ 26 апреля 2013

ОК, я публикую это через 2,5 года после того, как вопрос был задан впервые, но: вы рассматривали возможность использования вычисляемого столбца для столбца primary_duplicate вместо обычного столбца с привязкой по умолчанию?

Согласно MSDN , «constant_expression в определении DEFAULT не может ссылаться на другой столбец в таблице или на другие таблицы, представления или хранимые процедуры».

С другой стороны, вычисляемый столбец может.

Определите свою функцию следующим образом:

CREATE FUNCTION [dbo].[GetPrimaryDuplicate] 
(
   @id  uniqueidentifier,
   @catalog_timestamp datetime,
   @name nvarchar(255),
   @length bigint,
   @timestamp datetime    
)
RETURNS nchar(1)
AS 
BEGIN

IF EXISTS (
    SELECT  1
    FROM    FileCatalog
    WHERE   name=@name and length=@length and timestamp=@timestamp 
        and catalog_timestamp < @catalog_timestamp
)
    RETURN 'D' -- Duplicate

  RETURN 'P' -- Primary

END

Затем выполните следующую инструкцию ALTER TABLE:

GO
ALTER TABLE [dbo].[FileCatalog] DROP   COLUMN primary_duplicate 
ALTER TABLE [dbo].[FileCatalog] ADD    primary_duplicate as dbo.GetPrimaryDuplicate(id, catalog_timestamp, name, length, timestamp)
1 голос
/ 27 марта 2010

Вместо этого вы должны использовать триггер. Триггер получит копию вставленной строки.

...