如何对 Sql Server 列的默认绑定使用参数化函数

发布于 2024-08-27 11:16:50 字数 1609 浏览 5 评论 0原文

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

I have a table that catalogs selected files from multiple sources. I want to record whether a file is a duplicate of a previously cataloged file at the time the new file is cataloged. I have a column in my table (“primary_duplicate”) to record each entry as ‘P’ (primary) or ‘D’ (duplicate). I would like to provide a Default Binding for this column that would check for other occurrences of this file (i.e. name, length, timestamp) at the time the new file is being recorded.

I have created a function that performs this check (see “GetPrimaryDuplicate” below). But I don’t know how to bind this function which requires three parameters to the table’s “primary_duplicate” column as its Default Binding.

I would like to avoid using a trigger. I currently have a stored procedure used to insert new records that performs this check. But I would like to ensure that the flag is set correctly if an insert is performed outside of this stored procedure.

How can I call this function with values from the row that is being inserted?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

荒芜了季节 2024-09-03 11:16:50

好的,我是在第一次提出这个问题 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)

OK, I'm posting this 2.5 years after the question was first asked, but: have you considered using a calculated column for your primary_duplicate column, rather than a regular column with a default binding?

According to MSDN, "constant_expression in a DEFAULT definition cannot refer to another column in the table, or to other tables, views, or stored procedures."

A computed column, on the other hand, can.

Define your function as this:

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

Then execute the following ALTER TABLE statement:

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)
洋洋洒洒 2024-09-03 11:16:50

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

You should use a trigger instead. The trigger will receive a copy of the inserted row.

心清如水 2024-09-03 11:16:50

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

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

OP:抱歉,但我正在寻找相同的信息。

John, that isn't an answer to the question, and it's awfully presumptuous of you to assume that he should use a trigger. You don't know what he's trying to do or what reasons he might have for wanting to do it in default value.

If it's not possible, you might have said "That's not possible, so you should use a trigger instead" so he can actually learn something. I'm sure he knows as well as you do what triggers are and what they can be used for.

OP: Sorry, but I'm searching for the same information.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文