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