У меня отсутствует метод / ответ LINQ: -)
/// <summary>
/// Searches in the haystack array for the given needle using the default equality operator and returns the index at which the needle starts.
/// </summary>
/// <typeparam name="T">Type of the arrays.</typeparam>
/// <param name="haystack">Sequence to operate on.</param>
/// <param name="needle">Sequence to search for.</param>
/// <returns>Index of the needle within the haystack or -1 if the needle isn't contained.</returns>
public static IEnumerable<int> IndexOf<T>(this T[] haystack, T[] needle)
{
if ((needle != null) && (haystack.Length >= needle.Length))
{
for (int l = 0; l < haystack.Length - needle.Length + 1; l++)
{
if (!needle.Where((data, index) => !haystack[l + index].Equals(data)).Any())
{
yield return l;
}
}
}
}
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 :)
Так как другие предположили, что вы должны заглянуть в оператор MERGE, но никто не предоставил решение, использующее его, я добавляю свой собственный ответ с помощью этой конкретной конструкции TSQL. Бьюсь об заклад, вам понравится.
blockquote>Важное примечание
У вашего кода есть опечатка в вашем заявлении
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());
На первый взгляд ваша оригинальная попытка кажется довольно близкой. Я предполагаю, что 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
Как указывали другие, оператор слияния - это еще один способ решения этой же логики. Однако в некоторых случаях, особенно с большими наборами данных, заявление о слиянии может быть чрезмерно медленным, что приводит к большому количеству транзакций журнала. Поэтому знание того, как логично это сделать, как показано выше, по-прежнему является правильной техникой.
SET breakOut = GetDate()
будет обновляться до текущего времени. Просто имейте в виду, что если вы хотите сравнить значения (вместо того, чтобы устанавливать значение), вам нужно сделать первый, как этот ... where cast(getdate() as time(0)) = breatOut
.
– RThomas
10 August 2012 в 18:50
Вам нужно заменить его как WHERE clockDate = { fn CURRENT_DATE() } AND userName = 'test'
. Удалите лишний ")"
из { fn CURRENT_DATE() })