Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 динамические запросы в цикле  [new]
шкодер
Member

Откуда:
Сообщений: 6
Всем добрый день.

Перейду сразу к делу. Есть хранимая процедура, которой на вход поступает строка. Строка из себя содержит t-sql скрипт. Точнее несколько скриптов, разделенных "GO". Мне нужно засплитить эти скрипты и поочередно выполнить. Засплитить удалось без проблем при помощи дополнительной самописной функции. А вот с поочередным выполнением проблемы. Вот пример кода, который я использую.


DECLARE @scriptSplited nvarchar(max)
			DECLARE script_cursor CURSOR FOR
			SELECT ssc.script FROM dbo.Split(@script, 'GO') AS ssc;
			
			OPEN script_cursor;
			
			FETCH NEXT FROM script_cursor
			INTO @scriptSplited;

			WHILE (@@FETCH_STATUS = 0)
			BEGIN
				--INSERT INTO dbo.Table_1(b) VALUES(@scriptSplited);
				EXEC sp_executesql @scriptSplited;
				--INSERT INTO dbo.Table_1(c) VALUES(@scriptSplited);
				FETCH NEXT FROM script_cursor
				INTO @scriptSplited;
                --INSERT INTO dbo.Table_1(d) VALUES(@scriptSplited);
			END;
            --INSERT INTO dbo.Table_1(a) VALUES('blablabla')
			
			CLOSE script_cursor;
			DEALLOCATE script_cursor;
						
			INSERT INTO dbo.existingFeatures(title, feature, release, date)
			VALUES(@scriptName, @feature, @release, @date);


Как видно из скрипта, я совершаю манипуляции над входящей в процедуру строкой и выбираю этот результат в курсор.
Далее все по спеку, захожу в цикл и выполняю скрипт с помощью EXEC sp_executesql.

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

Есть подобный пример в msdn . Я его не проверял. Но предполагаю, что он рабочий. Мой же вариант практически не отличается и у меня с этим куча проблем.

Помогите пожалуйста пролить свет на данную ситуацию.

Заранее спасибо.

Сообщение было отредактировано: 8 ноя 12, 13:04
8 ноя 12, 13:03    [13439071]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
шкодер
Member

Откуда:
Сообщений: 6
Вот пример в msdn http://msdn.microsoft.com/ru-ru/library/ms175170(v=sql.105).aspx
8 ноя 12, 13:04    [13439080]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
шкодер
Последующие скрипты не выполняются.
И это подтверждается трассой профайлера? И что возвращает ваша замечательная функция, вы тоже уже проверили?
8 ноя 12, 13:07    [13439106]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
Glory
Member

Откуда:
Сообщений: 104751
шкодер
Так вот проблема заключается в том, что выполняется только первый скрипт. Последующие скрипты не выполняются.

А отуда вы знаете, сколько "скриптов" вы получили в курсоре ?
8 ноя 12, 13:08    [13439114]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
шкодер
Member

Откуда:
Сообщений: 6
Гавриленко Сергей Алексеевич
шкодер
Последующие скрипты не выполняются.
И это подтверждается трассой профайлера? И что возвращает ваша замечательная функция, вы тоже уже проверили?


Результат своей функции проверял. отрабатывает на 100% и возвращает она таблицу из одного столбца. Соответственно в каждой строке по 1 скрипту для дальнейшего выполнения.

Что за трасса профайлера? Можете подробней рассказать?

Glory
шкодер
Так вот проблема заключается в том, что выполняется только первый скрипт. Последующие скрипты не выполняются.

А отуда вы знаете, сколько "скриптов" вы получили в курсоре ?


Раскомменчиваю первый insert в цикле while и у меня в таблицу скидывается столько скриптов, сколько я задал во входном параметре процедуры.
8 ноя 12, 13:22    [13439217]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
шкодер,

показывайте функцию dbo.Split
8 ноя 12, 13:26    [13439253]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
Glory
Member

Откуда:
Сообщений: 104751
шкодер
Раскомменчиваю первый insert в цикле while и у меня в таблицу скидывается столько скриптов, сколько я задал во входном параметре процедуры.

Тогда откуда вы знаете, что "Последующие скрипты не выполняются." ? Где вы это видите ?
8 ноя 12, 13:29    [13439287]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
Кот Матроскин
Member

Откуда: Москва
Сообщений: 8933
Сделайте простой тестовый стенд - несколько скриптов вида "Insert into tabletest (column) values(...)".
Если он у Вас тоже не сработает, в таблице будет только одна запись - постите его сюда вместо со скриптом создания таблицы,
будем смотреть.
Если он сработает - значит проблема в Ваших конкретных скриптах.
8 ноя 12, 13:36    [13439383]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
шкодер
Member

Откуда:
Сообщений: 6
Вот код моей функции. Ничего сверхъестесственного тут не происходит.


FUNCTION [dbo].[Split] (
@string nvarchar(max),
@delimiter varchar(10)
)
RETURNS @splittedValues TABLE
(
[script] nvarchar(max)
)
AS
BEGIN
DECLARE
@SplitLength int,
@SubString nvarchar(max),
@stringTemp nvarchar(max)

SET @stringTemp = @string
WHILE Len(@stringTemp) > 0
BEGIN
SET @SplitLength = (CASE charindex(@delimiter,@stringTemp) WHEN 0 THEN
len(@stringTemp) ELSE charindex(@delimiter,@stringTemp) -1 END)
SET @SubString = Substring(@stringTemp, 1, @SplitLength)

INSERT INTO @splittedValues(script)
VALUES(@SubString)

SET @stringTemp = (case (len(@stringTemp) - @SplitLength) when 0 then ''
else right(@stringTemp, len(@stringTemp) - @SplitLength - len(@delimiter)) end)
END
RETURN
END


Почему я знаю, что последующие скрипты не выполняются. я для теста гоняю вот такой скрипт:


CREATE TABLE [dbo].[clarification_doc_details]
([fidTaxpayer] numeric(38, 0) NOT NULL,[KPP] char(9) NULL,[documentID] numeric(38, 0) NULL,[paymentDocID] numeric(38, 0) NULL)
GO
INSERT INTO [dbo].[document_types]([code], [name], [docKindID], [xsdName], [docRespType])
VALUES('65', '***********************************', 0, 'IU_PAYMENTDOC_1_01.xsd', NULL) GO


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

Еще более загадочный факт заключается в том. Что если я свою процедуру вызову в менеджмент студии и продебажу. То все отрабатывает просто замечательно. А вот когда я вызываю из консольного приложения, используя ADO.NET, то как раз и происходит описанная выше проблема.
8 ноя 12, 15:53    [13440612]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
aleks2
Guest
шкодер,

Нибось тебе ADO.net транзакцию открывает... а потом откатывает.
Оно и будет все хорошо и никаких ошибок.
8 ноя 12, 15:56    [13440630]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
aleks2
Guest
CREATE TABLE [dbo].[clarification_doc_details] 
([fidTaxpayer] numeric(38, 0) NOT NULL,[KPP] char(9) NULL,[documentID] numeric(38, 0) NULL,[paymentDocID] numeric(38, 0) NULL) 
GO 
INSERT INTO [dbo].[document_types]([code], [name], [docKindID], [xsdName], [docRespType])
VALUES('65', '***********************************', 0, 'IU_PAYMENTDOC_1_01.xsd', NULL) GO
GO
while @@trancount > 0 commit;
8 ноя 12, 15:57    [13440634]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
шкодер
Member

Откуда:
Сообщений: 6
aleks2,

Мы наверное с Вами не поняли друг друга.

Я беру и из шарпного кода вызываю хранимую процедуру. Параметром ей пихаю запрос в виде string, которая уже внутри самой процедуры разбивается на подзапросы и пытается в цикле последовательно их выполнить.

Вот шарпный код:


static void Main(string[] args)
{
const string commandsItem = "11111_2012081_24.09.2012 15-26.sql";
const string script = "CREATE TABLE [dbo].[clarification_doc_details] ([fidTaxpayer] numeric(38, 0) NOT NULL,[KPP] char(9) NULL,[documentID] numeric(38, 0) NULL,[paymentDocID] numeric(38, 0) NULL) GO INSERT INTO [dbo].[document_types]([code], [name], [docKindID], [xsdName], [docRespType]) VALUES('65', 'Заявление налогоплательщика об уточнении платежного документа, в котором налогоплательщик самостоятельно обнаружил ошибки в оформлении', 0, 'IU_PAYMENTDOC_1_01.xsd', NULL) GO";
const string conString = "Data Source=(local);Initial Catalog=testDB;Integrated Security=SSPI;";
using (var sqlConn = new SqlConnection(conString))
{
sqlConn.Open();
var command = sqlConn.CreateCommand();
var splitedCommandName = commandsItem.Split('_');
var feature = splitedCommandName[0];
var release = splitedCommandName[1];
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "proc1";
command.Parameters.Add(new SqlParameter("@scriptName",
commandsItem.Substring(0, commandsItem.LastIndexOf('.'))));
command.Parameters.Add(new SqlParameter("@script", script.Replace("\'", "\'\'")));
command.Parameters.Add(new SqlParameter("@feature", feature));
command.Parameters.Add(new SqlParameter("@release", release));
command.Parameters.Add(new SqlParameter("@date", DateTime.Now));
Console.WriteLine(commandsItem);
command.ExecuteNonQuery();

}
}


Вот как-то так все происходит. Объясните, пожалуйста, какую роль тут может играть транзакционность выполнения запросов через ADO.NET?

Спасибо,
Максим.
8 ноя 12, 16:29    [13440835]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
iiyama
Member

Откуда:
Сообщений: 642
жуете орбит 3,5 часа вместо того, чтобы потратить 30 сек на профайлер, хотя ... кому нужны простые пути ...
8 ноя 12, 16:43    [13440935]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
aleks2
Guest
Транзакция открывается на СОЕДИНЕНИИ с сервером.
И откатывается при разрыве
8 ноя 12, 16:43    [13440938]     Ответить | Цитировать Сообщить модератору
 Re: динамические запросы в цикле  [new]
шкодер
Member

Откуда:
Сообщений: 6
Вопрос снимается. Ошибка глупая. Спасибо, профайл помог правильно понять, какой запрос пытается выполниться.

Ошибка была в коде консольного приложения: script.Replace("\'", "\'\'")

Нужно передать script и на сервер запрос попадет с уже нужным кол-вом апострофов.
8 ноя 12, 17:23    [13441230]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить