Часто в проекте использую рекурсивные запросы (обобщённые табличные выражения), в частности для выборки данных из иерархических справочников (записи с полями ID, ID_PARENT, NAME - каждая запись ссылается на родительскую запись, аналог - стуктура файловой системы с каталогами и файлами). Начиная с SQL Server 2005 такие запросы можно строить с помощью конструкции WITH (Common table expression или обобщённые табличные выражения). Но обязательно требуется наличие символа ";" перед этим ключевым словом (как правило, везде пишут так ";WITH ...", но можно оставлять ";" и в конце предыдущей строки).
Для выполнения скриптов в программе используется компонент TMSScript, который считает символ ";" разделителем, из-за чего пакет SQL-команд разбивается на "ДО WITH" и "ПОСЛЕ WITH". Если в пакете перед WITH декларируются локальные переменные, то в самом WITH и после него эти переменные уже не видимы. Очистка свойства Delimiter у TMSScript не помогает.
Пример простейшего скрипта с применением WITH, полностью валидного с точки зрения SQL сервера:
Код: Выделить всё
procedure TForm1.Button6Click(Sender: TObject);
begin
MSScript2.SQL.Text := 'DECLARE @I SMALLINT ' +
'SELECT @I = 1 ' +
';WITH TAB (M) AS ( ' +
'SELECT @I ' +
'UNION ALL ' +
'SELECT CAST(T.M + 1 AS SMALLINT) ' +
'FROM TAB T ' +
'WHERE T.M < 10 ' +
') ' +
'SELECT * FROM TAB ' +
'GO';
MSScript2.Execute;
end;
При этом имеется такое наблюдение: если скрипт содержит ";WITH" в теле хранимой процедуры, то ";" игнорируется, и всё выполняется хорошо. Т.е. вы всё-таки производите какой-то анализ запроса, а не тупо разбиваете скрипт на выполняемые пакеты по символу ";".Неправильный синтаксис около конструкции ")".
Необходимо объявить скалярную переменную "@I".
Исправьте, пожалуйста.