Как добиться использования последовательности внутри оператора CASE MSSQL

В моем sql-запросе я хочу использовать последовательность внутри оператора CASE. Проблема в том, что я не могу использовать NEXT VALUE FOR внутри CASE. Я пытался определить пользовательскую функцию, но ограничения на использование exec и изменение данных в UDF сделали мое решение бесполезным...

Вот мой тестовый код:

    create sequence temp_test start with 1
select 
'value1',
'value2',
case when(1=1)
then next value for temp_test
else (select current_value from sys.sequences where name='temp_test')
end
drop sequence temp_test

Все, что мне нужно, это увеличить переменную, если условие истинно, и вернуть ее. Есть идеи?

Точная ошибка

Функцию NEXT VALUE FOR нельзя использовать в CASE, CHOOSE, COALESCE, IIF, ISNULL и NULLIF.


person Julian Kowalczuk    schedule 22.03.2017    source источник
comment
пожалуйста, добавьте некоторые примеры данных таблицы и ожидаемый результат - также в отформатированном тексте. Также покажите нам вашу текущую попытку запроса   -  person TheGameiswar    schedule 22.03.2017
comment
это не важно при решении этой проблемы, поэтому я изменю код, чтобы ясно показать, почему нет   -  person Julian Kowalczuk    schedule 22.03.2017
comment
Когда я запускаю create sequence temp_test starts with 1;, я получаю Incorrect syntax near 'starts'.. Пожалуйста, исправьте этот фрагмент вашего кода. Я также добавил сообщение об ошибке (пожалуйста, сделайте это в будущем). Что вы пытаетесь сделать?   -  person Nick.McDermaid    schedule 22.03.2017
comment
Кроме того, else temp_test недействителен. Вы пытаетесь получить текущее значение?   -  person Nick.McDermaid    schedule 22.03.2017
comment
исправлено. в любом случае, пожалуйста, сосредоточьтесь на цели задачи (как получить следующее значение внутри оператора case внутри оператора select)   -  person Julian Kowalczuk    schedule 22.03.2017
comment
Ясно, что это невозможно. Если вы объясните, что вы пытаетесь сделать, мы можем найти обходной путь.   -  person Nick.McDermaid    schedule 22.03.2017


Ответы (2)


Вместо прямой вставки в целевую таблицу сначала создайте временную таблицу и сначала установите идентификатор как нулевой, где необходимо установить последовательность. После этого обновите временную таблицу, строки идентификаторов которой равны нулю. После этого вставьте в целевую таблицу из временной таблицы.

Select case when @something = 1 then cast(null as int)
       else ID ends id,
       value
into #temp
from temp_test;

update #temp
set id = next value for [your_seq]
where id is null;
person Jose Tuttu    schedule 01.02.2020

Возможно, вы имеете в виду что-то вроде этого:

declare @value INT

SELECT @value = CAST(current_value AS INT) 
FROM sys.sequences WHERE name = 'temp_test';

IF (1=1)
    select  @value = next value for temp_test;


select 
'value1',
'value2',
@value

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

Возможно, вы сможете использовать identity, чтобы делать то, что хотите, или вы сможете написать это по-другому, но вы не объясните, что вы действительно пытаетесь сделать (например, загрузить новый ключ в таблицу?), поэтому больше не могу помочь

person Nick.McDermaid    schedule 22.03.2017
comment
нет, здесь вы устанавливаете значение из оператора select и case - person Julian Kowalczuk; 22.03.2017
comment
Пожалуйста, объясните, что вы на самом деле пытаетесь сделать. - person Nick.McDermaid; 22.03.2017
comment
Переменная, начинающаяся с 1. Я читаю данные из БД с помощью оператора select и внутри этого, если условие истинно, увеличиваю переменную и возвращаю ее с другими полями. - person Julian Kowalczuk; 22.03.2017
comment
Почему это нельзя сделать в двух утверждениях, как указано выше? Разрешено ли вам иметь пробелы (т. Е. Всегда увеличивать последовательность, но возвращаться только при необходимости) - person Nick.McDermaid; 22.03.2017
comment
Здесь есть большая картина, которая не объясняется. Поможет ли «идентификация»? - person Nick.McDermaid; 22.03.2017
comment
как вы видите в примере, увеличивайте, только если условие истинно, возвращайте значение ВСЕГДА для оператора выбора. Выбор в исходной версии получает данные из таблицы, и условие зависит от значений полей. - person Julian Kowalczuk; 22.03.2017
comment
Я на 99% уверен, что вы не можете сделать это во встроенном SELECT, вы должны сделать это процедурно. Я внесу изменения в свой ответ. Вы до сих пор не объяснили, почему это должен быть встроенный выбор. Куда идут данные? в другую таблицу? в отчет? - person Nick.McDermaid; 23.03.2017
comment
Проблема в том, что вы используете неправильный шаблон проектирования. Если у меня есть проблема с C#, я знаю, что обычно это происходит потому, что я делаю это неправильно, а не потому, что язык плохой. Я уверен, что то, что вы пытаетесь сделать, легко достижимо, если вы могли бы объяснить, почему вам нужно условно получить последовательность. Я уверен, что то, что вы пытаетесь сделать, не является чем-то из ряда вон выходящим. Вы пытаетесь генерировать новые идентификаторы на лету? на всякий случай, если эти записи будут вставлены позже? Какова реальная логика, чтобы решить, хотите ли вы новую последовательность или нет? - person Nick.McDermaid; 23.03.2017
comment
Я конвертирую запросы из postresql в mssql. Я знаю, что код, написанный авторами программы, которую мы рефакторим, имеет низкое качество, и они не должны использовать здесь последовательность, потому что она здесь не нужна. Но они используют, и все, что мне нужно сделать, это реализовать это в mssql. На лету я хочу увеличить переменную (это не обязательно должна быть последовательность), если условие истинно, и всегда включать ее в оператор выбора, чтобы вернуть ее с другими полями. Вот и все. - person Julian Kowalczuk; 23.03.2017
comment
Ответ, который я опубликовал, находится в операторе выбора. Вы получаете ошибку, когда пытаетесь реализовать это? - person Nick.McDermaid; 23.03.2017
comment
Должен ли номер быть глобально уникальным? (то есть без столкновений). Нужно ли увеличивать на 1? Это должно быть число? Если не должно быть коллизий (несколько параллельных вызовов получают свой уникальный идентификатор), то ваши варианты: sequence, identity или GUID. - person Nick.McDermaid; 23.03.2017
comment
да, это должно быть уникально. увеличьте только на 1. я знаю, что последовательность - это опция, личность и руководство точно нет. Я ищу любой хак, как это сделать, потому что ограничения mssql не позволяют сделать это четко... Вы задаете столько вопросов, но мы не зацикливаемся на цели. Я хочу получить данные из таблицы с дополнительным полем, зависящим от условия в скобках, возвращающего ту же переменную, но увеличить ее перед возвратом, если условие истинно. для меня как программиста это все, что я должен знать о проблеме. Я собираюсь найти помощь здесь среди спецификаций, и я надеюсь, что я - person Julian Kowalczuk; 24.03.2017
comment
Это невозможно сделать так, как вы хотите, поэтому я пытаюсь понять, что вы действительно хотите сделать, чтобы предложить обходной путь. Вот почему я задаю так много вопросов. Я уже предлагал одно решение ранее, но вы не объяснили, почему оно неудовлетворительно. Вы получаете ошибку? - person Nick.McDermaid; 24.03.2017
comment
Я уже ответил. Вы делаете это в операторе if, который нельзя использовать внутри select. Так что нет. - person Julian Kowalczuk; 27.03.2017
comment
Разве это не вариант, потому что у вас много сложного кода для переноса, и вам нужно простое шаблонное решение? Потому что вывод решения, которое я изложил, неотличим от любого другого автономного выбора, который делает все это встроенным. Должна быть какая-то синтаксическая причина, по которой вы не хотите делать это таким образом. Так что я еще раз скажу: вам нужно более подробно описать свои ограничения, чтобы мы могли придумать обходной путь. Основная проблема заключается в том, что элемент select сам по себе, предназначенный, не имеет всей блокировки, необходимой для обеспечения уникальности номера. - person Nick.McDermaid; 27.03.2017
comment
Я не говорю, что мой ответ правильный или подходит для вас. Это просто отправная точка для того, чтобы мы поняли друг друга. Если мой ответ не подходит, потому что «он использует if», то я не могу предложить ничего другого. Если вы говорите, что мой ответ не подходит, потому что ваш существующий код основан на представлениях, это дает мне ключ к предоставлению подходящего решения. Если вы реализуете мой код и получите ошибку, это также даст мне подсказку. - person Nick.McDermaid; 27.03.2017