SQL Server, CTE с IF EXISTS, затем обновлять существующие значения, иначе вставить [duplicate]

У меня отсутствует метод / ответ 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;
            }
        }
    }
}
54
задан Mark 26 May 2016 в 05:22
поделиться

4 ответа

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
ответ дан John Humphreys - w00te 19 August 2018 в 00:30
поделиться

Так как другие предположили, что вы должны заглянуть в оператор 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());
30
ответ дан Robert Koritnik 19 August 2018 в 00:30
поделиться
  • 1
    У меня есть некоторый запас в поиске прекрасного MERGE. – Steve 3 November 2017 в 18:39

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

Как указывали другие, оператор слияния - это еще один способ решения этой же логики. Однако в некоторых случаях, особенно с большими наборами данных, заявление о слиянии может быть чрезмерно медленным, что приводит к большому количеству транзакций журнала. Поэтому знание того, как логично это сделать, как показано выше, по-прежнему является правильной техникой.

52
ответ дан RThomas 19 August 2018 в 00:30
поделиться
  • 1
    clockDate - это тип данных 'date' NOT 'datetime'. Извините, что не уточнил. – tmhalbert 10 August 2012 в 18:41
  • 2
    вы можете отказаться от заявлений о действиях, тогда ... Я добавлю к своему сообщению. – RThomas 10 August 2012 в 18:42
  • 3
    Ох и breakOut - поле «время (0)» – tmhalbert 10 August 2012 в 18:47
  • 4
    Ничего страшного. SET breakOut = GetDate() будет обновляться до текущего времени. Просто имейте в виду, что если вы хотите сравнить значения (вместо того, чтобы устанавливать значение), вам нужно сделать первый, как этот ... where cast(getdate() as time(0)) = breatOut. – RThomas 10 August 2012 в 18:50
  • 5
    Иначе говоря. Вы можете установить дату, дату и время для getdate (). Двигатель sql достаточно умен, чтобы сделать работу по конверсии для вас. Это просто при сравнении значения, которое вы должны получить более конкретным. – RThomas 10 August 2012 в 18:54

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

2
ответ дан Suraj Shrestha 19 August 2018 в 00:30
поделиться
  • 1
    Извините, это была только опечатка с моей стороны. У меня есть это правильно в моем окне запросов SQL. – tmhalbert 10 August 2012 в 18:50
  • 2
    Спасибо, это отличная помощь для новичка. – Shahid Pro 6 August 2017 в 11:11
Другие вопросы по тегам:

Похожие вопросы: