Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: применение переменной вместо имени поля и таблицы в операторе select  (Прочитано 17260 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« : 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
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 02-07-2008 11:02 » 

Через динамический запрос.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #2 : 02-07-2008 11:10 » 

dimka,

прости, что ты имеешь в виду?
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 02-07-2008 12:32 » 

Malaja, интерпретация SQL-инструкции как строки. Но для начала нужно определиться с СУБД. На T-SQL вышеприведённый синтаксис не похож.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #4 : 02-07-2008 12:54 » 

dimka,

у меня sybase.

Клиент видит только процедуры и функции, прямые запросы посылать он не может (дабы своими шаловливыми ручками чего не наделать).
Сейчас появились новые таблицы, соответственно должны появиться новые процедуры и функции. Но т.к. новая группа таблиц крутится вокруг одной основной (у них у всех foreign key определен как поле из этой основной таблицы), то при определенных операциях надо все время делать одно и то же. Не хочется повторять код 6 раз..
Вот и решила сделать как в обычном языке программирования.
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #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;

Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline 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
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #7 : 23-07-2008 07:52 » 

Леш,

клиенту об этом ничего не должно быть известно.
Принцип таков: со стороны базы данных надо подготовить серию views и stored procedures на все случаи жизни клиентов (т.е. разработчиков софта). Далее, для этих самых клиентов все идет по принципу работы с чужой dll - у них есть список функций (тех самых views и т.д.), которые они могут вызывать с помощью с/с++/с# (кто во что гаразд Ага ).
Поэтому предложить им заполнить темплейт невозможно.
А моя сторона - чистый sql, где создать такие навороты в принципе нереально.

Вот такие вот пирожки... Вот и приходится извращаться Ага
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 23-07-2008 15:23 » 

кстати, в интербейсе больше одной строки выбирается в прцедуре так (синтаксис сейчас не проверял, но принцип такой)-

Код:
 for select * from T1 where .... into :x1,:x2,:x3 ...
  do
  begin
    //... тут можно что то с полями ещё сделать
  end

и вот вопрос - у тебя так низя ? )
Записан

Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #9 : 24-07-2008 10:50 » 

Леш,

Проверила, не катит ;-(
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 24-07-2008 13:57 » 

Malaja, ой, я забыл: класть строку надо suspend:

Код:
for select * from T1 where .... into :x1,:x2,:x3 ...
  do
  begin
    /*... тут можно что то с полями ещё сделать*/
    suspend; /*кладём запись в результат*/
  end
Записан

Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #11 : 24-07-2008 16:06 » 

Леш,

у них такой команды нет.
Насколько я понимаю, это уже особенности национальной охоты баз данных - кто во что гаразд. Они в принципе используют стандартный sql, но плюс к этому каждый вводит что-то свое, вот и имеем в результате то, что имеем.
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 24-07-2008 16:59 » 

даа, в результате база имеет нас )
Записан

Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #13 : 25-07-2008 06:57 » 

Ага Ага А если база нас побеждает, тогда нас имеет начальство Ага
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 25-07-2008 08:45 » new

то есть база, практически, использует начальство Улыбаюсь)
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines