Подтвердить что ты не робот

SQL Server 2008 - ЕСЛИ НЕ СУЩЕСТВУЕТ ВСТАВИТЬ ДОПОЛНИТЕЛЬНОЕ ОБНОВЛЕНИЕ

Извиняюсь, но это вопрос двух частей.

Я чрезвычайно новичок в 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-запроса Compound не поддерживается". Однако за этим следует сообщение о том, что 1 строка была затронута, и когда я просматриваю свою таблицу Clock, она выглядит так же, как я ожидаю, что она будет выглядеть. Каков наилучший способ обмануть это?

И моя вторая часть этого вопроса находится в моих заявлениях WHERE. Есть функция, чтобы получить сегодняшнюю дату в столбце clockDate вместо того, чтобы заполнять сегодняшнюю дату? Просто пытаюсь задуматься над созданием приложения на передней панели.

    IF NOT EXISTS(SELECT * FROM Clock WHERE clockDate = { fn CURRENT_DATE() }) AND userName = 'test')

Опять же, это дает мне результаты, которые я хочу, но только после получения ошибки "Ошибка в предложении WHERE рядом с" CURRENT_DATE ". Невозможно разобрать текст запроса.

Надеюсь, я объяснил это правильно, и спасибо за вашу помощь!

EDIT:

@RThomas @W00te

Хорошо, так что с clockDate как поле даты и breakOut как поле времени (0), должно ли это работать? Причина, по которой я все еще получаю "Конструкция или оператор SQL-запроса Compound, не поддерживается". Синтаксическая ошибка, даже если она работает.

    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? И я буду читать сообщения о слиянии, спасибо вам за ссылки.

4b9b3361

Ответ 1

На первый взгляд ваша первоначальная попытка кажется довольно близкой. Я предполагаю, что 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 (только дата), тогда 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 

Ответ 2

Как другие предположили, что вы должны заглядывать в оператор MERGE, но никто не предоставлял решение, используя его. Я добавляю свой собственный ответ с этой конкретной конструкцией TSQL. Бьюсь об заклад, вам понравится.

Важное примечание

В вашем коде есть опечатка в инструкции if в разделе not exists(select...). Внутренний оператор select имеет только одно условие where, в то время как условие UserName исключается из not exists из-за недопустимого завершения скобки. В любом случае вы слишком много закрываете скобки.

Я предполагаю, что это основано на том, что вы используете два where условия в выражении update позже в своем коде.

Продолжим мой ответ...

SQL Server 2008+ поддерживает оператор MERGE

Утверждение MERGE - красивый драгоценный камень TSQL, очень подходящий для ситуаций "вставки или обновления". В вашем случае это будет похоже на следующий код. Примите во внимание, что я объявляю переменные, которые являются вероятными параметрами хранимой процедуры (я подозреваю).

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());

Ответ 3

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) предоставит вам только дату (не время).

IF NOT EXISTS(SELECT * FROM Clock WHERE
clockDate = CONVERT(varchar(8), GETDATE(), 112)
AND userName = 'test')

должен, вероятно, сделать это.

PS: используйте merge:)

Ответ 4

Вам нужно заменить его как WHERE clockDate = { fn CURRENT_DATE() } AND userName = 'test'. Удалите лишний ")" из { fn CURRENT_DATE() })