Malaja
|
|
« : 02-07-2008 09:17 » |
|
Господа, ситуация следующая: необходимо делать операцию delete для нескольких таблиц. В принципе для каждого случая надо написать свою stored procedure для этого. Но т.к. за исключением имен таблиц и полей все остальное д.б. одинаково, возникает совершенно справедливое желание сделать одну общую функцию для всех этих процедур. Сделала. Не работает... Т.е. при выполнении говорит, что не находит такое поле или такую таблицу. Вопрос на засыпку: 1) насколько это вообще возможно 2) если да, что что не так в коде: create procedure prime.deleteNotificationElement ( in p_nNotificationId integer, in p_szFieldName varchar (60), in p_szTableName varchar (60), in p_szFunctionName varchar (60), out p_nRetValue integer ) begin atomic
// всякие обработки, сообщения в лог и т.д.
delete from p_szTableName where p_szFieldName = p_nNotificationId; end;
create procedure prime.deleteFaultLocatorNotification ( in p_nFaultLocatorNotificationId integer ) begin atomic
declare p_nRetValue integer; call prime.deleteNotificationElement (p_nFaultLocatorNotificationId, 'FaultLocatorNotificationId', 'syNotificationFaultLocatorAssignment', 'deleteFaultLocatorNotification', p_nRetValue);
if (p_nRetValue = -1) then raiserror FaultLocatorNotificationIdNotFound; end if
end;
Заранее благодарю за помощь.
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #1 : 02-07-2008 11:02 » |
|
Через динамический запрос.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Malaja
|
|
« Ответ #2 : 02-07-2008 11:10 » |
|
dimka,
прости, что ты имеешь в виду?
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #3 : 02-07-2008 12:32 » |
|
Malaja, интерпретация SQL-инструкции как строки. Но для начала нужно определиться с СУБД. На T-SQL вышеприведённый синтаксис не похож.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Malaja
|
|
« Ответ #4 : 02-07-2008 12:54 » |
|
dimka,
у меня sybase.
Клиент видит только процедуры и функции, прямые запросы посылать он не может (дабы своими шаловливыми ручками чего не наделать). Сейчас появились новые таблицы, соответственно должны появиться новые процедуры и функции. Но т.к. новая группа таблиц крутится вокруг одной основной (у них у всех foreign key определен как поле из этой основной таблицы), то при определенных операциях надо все время делать одно и то же. Не хочется повторять код 6 раз.. Вот и решила сделать как в обычном языке программирования.
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Malaja
|
|
« Ответ #5 : 22-07-2008 08:58 » |
|
Я тут немного разобралась, и, пока дошли ручки, пишу сюда, вдруг кто-то еще с этим столкнется. Для стандартных баз данных можно использовать вот такое: test.sql:
declare tableName as varchar(128); declare fieldName as varchar(128);
set tableName = 'testTable'; set fieldName = 'testField'; call testFunc(tableName, fieldName);
cerate function testFunc ( in tableName varchar(128), in fieldName varchar(128) ) returns integer begin atomic
select @fieldName from @tableName;
end;
В sybase это не работает... Посему сработало вот что: cerate function testFunc ( in tableName varchar(128), in fieldName varchar(128), in fieldVal varchar (128) ) returns integer begin atomic
declare szTmp varchar(4000); declare @res integer;
set szTmp = 'select ' || fieldName || ' INTO @res from ' || tableName || ' where ' || fieldName || ' = ' || fieldVal; EXECUTE IMMEDIATE szTmp; MESSAGE @res || ' records' TO CLIENT; -- получим количество строк, возвращенных нам командой select
-- если же результатом select может быть более одной строки, -- тогда первый вариант не подходит (при выполнении появится sql-error). -- В этом случае надо делать следующее: set szTmp = 'select COUNT (*) INTO @res from ' || tableName || ' where ' || fieldName || ' = ' || fieldVal; message ' AFTER EXECUTE count = ', @@rowcount to client; -- получим количество строк, возвращенных нам командой select
end;
Если же нам надо не только узнать количество строк, но и получить для дальнейшего использования стоящую в таблице информацию, надо использовать временную таблицу и курсор:
cerate function testFunc ( in tableName varchar(128), in fieldName1 varchar(128), in fieldName2 varchar(128), in fieldName varchar(128), in fieldVal varchar (128) ) returns integer begin atomic
-- наша временная таблица DECLARE LOCAL TEMPORARY TABLE tmpTable ( Field1 varchar(256), Field2 varchar(32) ) NOT TRANSACTIONAL;
declare nSaveErrorMsg long varchar; declare nSaveError integer; declare nSaveSqlCode varchar(5); declare szField1 varchar(256); declare szField2 varchar(32); declare szTmpInfo varchar(4000);
begin
-- создаем запрос set szTmpInfo = 'select ' || fieldName1 || ', ' || fieldName2 || ' from ' || tableName || ' where ' fieldName || ' = ' || fieldVal;
-- объявляем курсор, основанный на нашемм запросе declare tmpTableCurs cursor using szTmpInfo;
-- открываем его, идем построчно по результатам open tmpTableCurs; tmpTableCursLoop: loop
fetch next tmpTableCurs into szField1, szField2;
--error by fetch next if sqlcode <> 0 then select sqlstate, @@error, errormsg() into nSaveSqlCode, nSaveError, nSaveErrorMsg; leave tmpTableCursLoop end if;
-- каждую строку, полученную в результате select-а вносим в нашу временную таблицу insert into tmpTable (Field1, Field2) values (szField1, szField2 );
end loop tmpTableCursLoop; close tmpTableCurs; end;
-- теперь мы можем работать с результатами как с обычной таблицей, например: select Field1 from tmpTable where Field2 = '1';
end;
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #6 : 22-07-2008 16:18 » |
|
Malaja, как вариант - перед работой проверять в базе и заливать при необходимости код процедуры. Для процедуры сделать текстовый шаблон: const char* template= "\r\ncreate function testFunc " "\r\n( in %s , in %s, " "\r\n in %s, in %s, " "\r\n in %s )" "\r\nreturns integer" "\r\nbegin atomic" "\r\n" "\r\n -- наша временная таблица" "\r\n DECLARE LOCAL TEMPORARY TABLE %s " "\r\n (" "\r\n %s," "\r\n %s)" "\r\n ) NOT TRANSACTIONAL; " ... ...
CString Proc; Proc.Format(template,...,...,...,...,...);
...->ExequteSql(Proc);
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #7 : 23-07-2008 07:52 » |
|
Леш, клиенту об этом ничего не должно быть известно. Принцип таков: со стороны базы данных надо подготовить серию views и stored procedures на все случаи жизни клиентов (т.е. разработчиков софта). Далее, для этих самых клиентов все идет по принципу работы с чужой dll - у них есть список функций (тех самых views и т.д.), которые они могут вызывать с помощью с/с++/с# (кто во что гаразд ). Поэтому предложить им заполнить темплейт невозможно. А моя сторона - чистый sql, где создать такие навороты в принципе нереально. Вот такие вот пирожки... Вот и приходится извращаться
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #8 : 23-07-2008 15:23 » |
|
кстати, в интербейсе больше одной строки выбирается в прцедуре так (синтаксис сейчас не проверял, но принцип такой)- for select * from T1 where .... into :x1,:x2,:x3 ... do begin //... тут можно что то с полями ещё сделать end
и вот вопрос - у тебя так низя ? )
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #9 : 24-07-2008 10:50 » |
|
Леш,
Проверила, не катит ;-(
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #10 : 24-07-2008 13:57 » |
|
Malaja, ой, я забыл: класть строку надо suspend: for select * from T1 where .... into :x1,:x2,:x3 ... do begin /*... тут можно что то с полями ещё сделать*/ suspend; /*кладём запись в результат*/ end
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #11 : 24-07-2008 16:06 » |
|
Леш,
у них такой команды нет. Насколько я понимаю, это уже особенности национальной охоты баз данных - кто во что гаразд. Они в принципе используют стандартный sql, но плюс к этому каждый вводит что-то свое, вот и имеем в результате то, что имеем.
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #12 : 24-07-2008 16:59 » |
|
даа, в результате база имеет нас )
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #13 : 25-07-2008 06:57 » |
|
Ага А если база нас побеждает, тогда нас имеет начальство
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #14 : 25-07-2008 08:45 » |
|
то есть база, практически, использует начальство )
|
|
|
Записан
|
|
|
|
|