1

我有一个表格,对来自多个来源的选定文件进行编目。我想在对新文件进行编目时记录文件是否与以前编目的文件重复。我的表中有一个列(“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
4

3 回答 3

2

约翰,这不是问题的答案,你认为他应该使用触发器是非常冒昧的。您不知道他想要做什么,也不知道他可能出于什么原因想要以默认值执行此操作。

如果不可能,你可能会说“那不可能,所以你应该使用触发器”,这样他才能真正学到一些东西。我相信他和你一样知道触发器是什么以及它们可以用来做什么。

OP:对不起,我正在寻找相同的信息。

于 2010-10-25T18:41:05.493 回答
2

好的,我在第一次提出这个问题 2.5 年后发布了这篇文章,但是:您是否考虑过为您的列使用计算列primary_duplicate,而不是使用默认绑定的常规列?

根据MSDN,“DEFAULT 定义中的 constant_expression 不能引用表中的另一列,也不能引用其他表、视图或存储过程。”

另一方面,计算列可以。

将您的功能定义为:

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)
于 2013-04-26T15:34:14.650 回答
1

您应该改用触发器。触发器将接收插入行的副本。

于 2010-03-27T06:01:02.913 回答