Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server 2008-如果不存在,请插入ELSE更新_Sql_Sql Server 2008 - Fatal编程技术网

SQL Server 2008-如果不存在,请插入ELSE更新

SQL Server 2008-如果不存在,请插入ELSE更新,sql,sql-server-2008,Sql,Sql Server 2008,很抱歉,这是一个分为两部分的问题 我对SQL非常陌生,正在尝试为我工作的小办公室开发一个时钟应用程序。我现在正在玩SQL后端,对复合语句有一个问题 我陷入困境的地方是,如果用户试图在休息时打卡,但从未在轮班开始时打卡,SQL需要创建新行,而不是更新现有行 以下是我尝试过的: IF NOT EXISTS(SELECT * FROM Clock WHERE clockDate = '08/10/2012') AND userName = 'test') BEGIN I

很抱歉,这是一个分为两部分的问题

我对SQL非常陌生,正在尝试为我工作的小办公室开发一个时钟应用程序。我现在正在玩SQL后端,对复合语句有一个问题

我陷入困境的地方是,如果用户试图在休息时打卡,但从未在轮班开始时打卡,SQL需要创建新行,而不是更新现有行

以下是我尝试过的:

    IF NOT EXISTS(SELECT * FROM Clock WHERE clockDate = '08/10/2012') AND userName = 'test')
    BEGIN
        INSERT INTO Clock(clockDate, userName, breakOut)
        VALUES({ fn NOW() }, 'test', { fn NOW() })
    END
    ELSE
    BEGIN
        UPDATE Clock
        SET breakOut = { fn NOW() }
        WHERE (clockDate = '08/10/2012') AND (userName = 'test')
    END
我正在使用Visual Studio 2010在本地计算机上连接到SQL Server Express 2008来完成此操作。我得到了一个错误,上面写着“不支持复合语句SQL构造或语句”。但是,后面是一条消息,表明1行受到了影响,当我查看时钟表时,它看起来就像我期望的那样。最好的办法是什么

这个问题的第二部分在我的WHERE语句中。是否有一个函数可以在clockDate列中获取今天的日期,而不必填充今天的日期?只是试着提前考虑构建前端应用程序

    IF NOT EXISTS(SELECT * FROM Clock WHERE clockDate = { fn CURRENT_DATE() }) AND userName = 'test')
同样,这会给我想要的结果,但直到在“CURRENT_DATE”附近的WHERE子句中出现错误“error”。无法解析查询文本之后

我希望我已经解释清楚了,谢谢你的帮助

编辑:

@关节瘤 @w00te

好的,那么clockDate作为一个日期字段,breakOut作为一个时间(0)字段,应该这样做吗?因为我仍然得到一个“复合语句SQL构造或语句不受支持。”语法错误,即使它似乎正在工作

    IF NOT EXISTS (SELECT * FROM Clock WHERE (clockDate = GETDATE()) AND (userName = 'test'))
    BEGIN
        INSERT INTO Clock(clockDate, userName, breakOut)
        Values(GETDATE(), 'test', GETDATE())
    END
    ELSE
    BEGIN
        UPDATE Clock
        SET breakOut = GETDATE()
        WHERE (clockDate = GETDATE()) AND (userName = 'test')
    END
我的表格结果如下:

clockDate  userName  clockIn  breakOut  breakIn  clockOut

08/10/2012  test      NULL    11:24:38   NULL     NULL
这是我想要的结果,但这个错误使我困惑。这是Visual Studio错误还是SQL错误?我会阅读合并语句,谢谢你们的链接

IF NOT EXISTS(SELECT * FROM Clock
WHERE clockDate = '08/10/2012') AND userName = 'test')
有一个额外的括号。我想如果你把它取下来就好了:

IF NOT EXISTS(SELECT * FROM Clock WHERE
clockDate = '08/10/2012' AND userName = 'test')
此外,GETDATE()将把当前日期放在列中,不过如果您不想占用时间,就必须玩一点。我认为CONVERT(varchar(8),GETDATE(),112)只会给出日期(而不是时间)部分

我可能应该这么做


PS:使用语句:)

您需要将其替换为
,其中clockDate={fn CURRENT_DATE()}和userName='test'

请从
{fn CURRENT_DATE()}中删除额外的

乍一看,您最初的尝试似乎非常接近。我假设clockDate是DateTime字段,因此请尝试以下方法:

IF (NOT EXISTS(SELECT * FROM Clock WHERE cast(clockDate as date) = '08/10/2012') 
    AND userName = 'test') 
BEGIN 
    INSERT INTO Clock(clockDate, userName, breakOut) 
    VALUES(GetDate(), 'test', GetDate()) 
END 
ELSE 
BEGIN 
    UPDATE Clock 
    SET breakOut = GetDate()
    WHERE Cast(clockDate AS Date) = '08/10/2012' AND userName = 'test'
END 
请注意,getdate为您提供了当前日期。如果试图与日期(没有时间)进行比较,则需要强制转换,否则时间元素将导致比较失败


如果clockDate不是datetime字段(只是date),那么SQL引擎将为您执行此操作—无需强制转换set/insert语句

IF (NOT EXISTS(SELECT * FROM Clock WHERE clockDate = '08/10/2012') 
    AND userName = 'test') 
BEGIN 
    INSERT INTO Clock(clockDate, userName, breakOut) 
    VALUES(GetDate(), 'test', GetDate()) 
END 
ELSE 
BEGIN 
    UPDATE Clock 
    SET breakOut = GetDate()
    WHERE clockDate = '08/10/2012' AND userName = 'test'
END 
正如其他人所指出的,merge语句是处理相同逻辑的另一种方法。但是,在某些情况下,特别是对于大型数据集,merge语句的速度可能会非常慢,导致大量事务日志活动。因此,知道如何如上所示进行逻辑推理仍然是一种有效的技术

正如其他人所建议的,您应该研究MERGE语句,但没有人提供使用它的解决方案,我正在使用这个特殊的TSQL构造添加我自己的答案。我打赌你会喜欢的

重要提示 如果
部分中的
语句不存在(选择…
部分),则您的
中存在键入错误。内部
select
语句只有一个
,其中
条件,而用户名条件由于大括号填空无效而被排除在
不存在的范围之外。在任何情况下,你都有太多的结束括号

我假设这是基于这样一个事实,即您在代码后面的
update
语句中使用了两个
where
条件

让我们继续我的答案

SQL Server 2008+支持合并语句 是一个漂亮的TSQL gem,非常适合“插入或更新”情况。在您的情况下,它看起来类似于下面的代码。考虑到我声明的变量可能是存储过程参数(我怀疑)


请查看该语句。尽管我在下面给出了答案,但我同意其他人的看法,即当您不确定值是否已经存在时,合并语句是处理插入/更新场景的一种很好的方法。下面是我不久前发布的merge语句的演练。如果你想了解更多关于它是如何工作的,这就是MERGE语句的用途!请注意,在某些情况下,特别是对于大型数据集,merge语句的速度可能会非常慢,导致大量事务日志活动。因此,知道如何将其逻辑化仍然有效。clockDate是“日期”数据类型,而不是“日期时间”。很抱歉没有澄清这一点。你可以放弃演员声明,然后。。。我会添加到我的帖子中。哦,突破是一个“时间(0)”字段,没关系
SET breakOut=GetDate()
仍将更新到当前时间。请注意,如果您想要比较值(而不是设置值),您需要像这样先强制转换
where cast(getdate()作为时间(0))=breatOut
。换句话说。您可以将日期、日期时间和时间设置为getdate()。sql引擎足够智能,可以为您完成转换工作。只是在比较价值时,你必须更具体。对不起,这只是我的一个输入错误。在我的SQL查询窗口中,它是正确的。在查找“合并”时,我有一些保留。在您尝试在远程表上使用“合并”之前,一切都很好。。为什么?
IF (NOT EXISTS(SELECT * FROM Clock WHERE clockDate = '08/10/2012') 
    AND userName = 'test') 
BEGIN 
    INSERT INTO Clock(clockDate, userName, breakOut) 
    VALUES(GetDate(), 'test', GetDate()) 
END 
ELSE 
BEGIN 
    UPDATE Clock 
    SET breakOut = GetDate()
    WHERE clockDate = '08/10/2012' AND userName = 'test'
END 
declare @clockDate date = '08/10/2012';
declare @userName = 'test';

merge Clock as target
using (select @clockDate, @userName) as source (ClockDate, UserName)
on (target.ClockDate = source.ClockDate and target.UserName = source.UserName)
when matched then
    update
    set BreakOut = getdate()
when not matched then
    insert (ClockDate, UserName, BreakOut)
    values (getdate(), source.UserName, getdate());