【问题标题】:Insert data based on non existence and different criteria's [closed]根据不存在和不同标准插入数据[关闭]
【发布时间】:2020-12-30 23:47:14
【问题描述】:

我试图仅在两个条件下向我的表中添加一行,但插入时会检索错误,我无法弄清楚


 Create PROC [dbo].[setvisitorqueue]
 @pid bigint = null , @vid int = NULL ,@regdate nvarchar(50)  =NULL 

 AS 

 declare @queNum int =null
 set @queNum = (select max([ticketNo]) + 1 from [dbo].[queue] where [ticketdate]= GetDate())
 if( @queNum is null) begin  set @queNum=1 end

 Declare @Tktt int = null  

 set @Tktt = (select count(queue.ticketid) from queue where (queue.pid = @pid )and (queue.ticketdate = GetDate()) and (queue.vid = @vid and queue.checked = 0))

 if (@Tktt is null ) 
 begin insert into queue (vid , pid , ticketNo , ticketdate ) Values (@Vid,@pid,@queNum,@regdate ) end

它不适合我。

【问题讨论】:

  • 错误是什么?
  • 只提到返回值=0 一行成功影响
  • 1) 请edit 对您的问题进行任何澄清。 2) 请显示一些示例数据和预期结果,包括表中的值以及对带有值的 SP 的调用。
  • 请阅读this,了解一些改进问题的技巧。为queue 添加 DDL 将消除有关数据类型的一些谜团。

标签: sql sql-server tsql stored-procedures


【解决方案1】:

你可以试试这样简单的方法吗?

CREATE PROC [dbo].[setvisitorqueue]
@pid BIGINT = null,
@vid INT = NULL,
@regdate NVARCHAR(50) = NULL 
AS 
    
IF (
    SELECT COUNT(ticketid) 
    FROM [dbo].[queue] 
    WHERE checked = 0 and pid = @pid and vid = @vid and ticketdate = GetDate()
    ) = 0
INSERT INTO [dbo].[queue](vid  pid, ticketdate, ticketNo  ) 
SELECT @Vid, @pid, @regdate, ticketNo = IsNull(MAX([ticketNo]),0) + 1
FROM [dbo].[queue] 
WHERE [ticketdate]= GetDate();

RETURN;
GO

在这段代码中,我完成了以下操作:

  1. 通过 Caps、intent、空格等提高了可读性。
  2. 已消除的变量 - 您在该代码中不需要它们 您不需要 如果不使用,则需要在开始时计算“TicketNo”。 因此,如果需要,它将在 IF 语句中进行计算。
  3. 您不需要在每个事务上都使用 BEGIN-END,单 请求是一个事务

不确定您的错误是什么,但您的程序不会做任何事情,因为当您执行“COUNT”时它会返回一个数字。这意味着您的“@Tktt”变量永远不会为 NULL。

我猜你的意图是在没有找到记录并将“COUNT”查询与“0”值进行比较时运行 Insert 语句。

【讨论】:

  • 非常感谢它对我有用我刚刚用 @regdate 更改了 GetTime(),一切都很好:)
  • “您不需要在每个事务上都使用 BEGIN-END”我认为您的意思是条件语句块 - 因为 begin/end 肯定没有定义事务。但是我会不同意,我个人总是使用开始/结束条件语句块来澄清。否则很容易出错 - 但这只是我的看法。
  • @DaleK 在这种情况下,当有单个语句时,没有必要。如果有更复杂的逻辑,肯定需要它。就我个人而言,我试图避免任何不必要的关闭,因为它们会使代码的可读性降低,并且可能不会注意到错误。但那是“个人风格”的讨论。
【解决方案2】:

这是您的 SP,其中包含我发现的所有问题,并已通过 cmets 进行了纠正,并添加了最佳实践。正如其他答案所述,您可能可以简化事情。我的目标只是纠正现有的问题。

-- NOTES: Keep your casing and layout consistent
-- Always terminate statements with a semi-colon
-- Don't add un-necessary brackets, they just clutter the code
-- You also have a concurrency issue:
--   if this proc is called twice at the same time you could issue the same ticket number twice

create proc [dbo].[setvisitorqueue]
(
    @pid bigint = null,
    @vid int = null,
    -- Only every use a datetime/date datatype to store a datatime/date. Datetime2 is the current standard. Change precision to suit.
    @regdate datetime2(0) = null
)
as
begin
    -- Always start your SP with
    set nocount, xact_abort on;

    declare @queNum int = null;

    set @queNum = (
        select max([ticketNo]) + 1
        from dbo.[queue]
        -- This seems very unlikely to happen? It has to match down to the fraction of a second.
        where [ticketdate] = getdate()
    );

    if @queNum is null begin
        set @queNum = 1;
    end;

    declare @Tktt int = null;

    -- @Tktt will *never* be null after this, it may be zero though.    
    set @Tktt = (
        select count(*)
        from dbo.[queue]
        where pid = @pid
        -- This seems very unlikely to happen? It has to match down to the fraction of a second.
        and ticketdate = getdate()
        and vid = @vid and checked = 0
    );

    -- Handle 0 or null just in case
    -- if @Tktt is null -- THIS IS WHAT PREVENTED YOUR INSERT
    if coalesce(@Tktt,0) = 0 
    begin
        insert into dbo.[queue] (vid, pid, ticketNo, ticketdate)
            values (@Vid, @pid, @queNum, @regdate);
    end;

    -- Always return the status of the SP, 0 means OK
    return 0;
end;

【讨论】:

    猜你喜欢
    • 2018-09-25
    • 2012-11-16
    • 1970-01-01
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    相关资源
    最近更新 更多