Локальные переменные в скрипте Informix

#informix

#informix

Вопрос:

Я должен выполнить большой скрипт обновления, а не SPL (хранимую процедуру). Это должно быть написано для базы данных Informix.

Это включает в себя вставку строк в несколько таблиц, каждая из которых зависит от порядкового номера вставки в предыдущую таблицу.

Я знаю, что могу получить доступ к серийному номеру, выполнив это:

 SELECT DISTINCT dbinfo('sqlca.sqlerrd1') FROM systables
  

но, похоже, я не могу определить локальную переменную для сохранения этого перед вставкой в следующую таблицу.

Я хочу сделать это:

 insert into table1 (serial, data1, data2) values (0, 'newdata1', 'newdata2');
define serial1 as int;
let serial1 = SELECT DISTINCT dbinfo('sqlca.sqlerrd1') FROM systables;
insert into table2 (serial, data1, data2) values (0, serial1, 'newdata3');
  

Но, конечно, Informix блокирует строку определения.

Есть ли способ сделать это без необходимости создавать это как хранимую процедуру, запускать ее один раз, а затем удалять процедуру?

Ответ №1:

Если количество столбцов в задействованных таблицах так же мало, как в вашем примере, то вы могли бы сделать SPL постоянным и использовать его для вставки ваших данных, т.Е.:

EXECUTE PROCEDURE insert_related_tables('newdata1','newdata2','newdata3');

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

Другая мысль, которая развивает пример Джонатана и решает любые проблемы параллелизма, которые могут возникнуть при использовании MAX(), заключалась бы в том, чтобы включить DBINFO('sessionid') в Table3 :

 DELETE FROM Table3 WHERE sessionid = DBINFO('sessionid');
INSERT INTO Table1 (...);
INSERT INTO Table3 (sessionid, value)
  VALUES (DBINFO('sessionid'), DBINFO('sqlca.sqlerrd1'));
INSERT INTO Table2 
  VALUES (0, (SELECT value FROM Table3
              WHERE sessionid = DBINFO('sessionid'), 'newdata3');
...
  

Вы также могли бы создать Table3 временную таблицу:

 INSERT INTO Table1 (...);
SELECT DISTINCT DBINFO('sqlca.sqlerrd1') AS serial_value
  FROM some_dummy_table_like_systables
INTO TEMP Table3 WITH NO LOG;
INSERT INTO Table2 (...);
  

Комментарии:

1. Я опустил TEMP из моей Таблицы3, что приводит к проблемам параллелизма; поскольку это временная таблица, проблем с параллелизмом нет, потому что она содержит только значения для текущего сеанса. Я везде писал SQL с TEMP и был слишком увлечен удалением TEMP. Тем не менее, хороший момент.

Ответ №2:

Informix не предоставляет механизм вне хранимых процедур для «локальных переменных» нужного вам типа. Однако в ограниченном примере, который вы предоставляете, это работает:

 CREATE TABLE Table1
(
    serial SERIAL(123) NOT NULL,
    data1  VARCHAR(32) NOT NULL,
    data2  VARCHAR(32) NOT NULL
);
CREATE TABLE Table2
(
    serial SERIAL      NOT NULL,
    data1  INTEGER     NOT NULL,
    data2  VARCHAR(32) NOT NULL
);

INSERT INTO Table1(Serial, Data1, Data2)
    VALUES(0, 'newdata1', 'newdata2');
INSERT INTO Table2(Serial, Data1, Data2)
    VALUES(0, DBINFO('sqlca.sqlerrd1'), 'newdata3');

SELECT * FROM Table1;

123   newdata1     newdata2

SELECT * FROM Table2;

1     123          newdata3
  

Однако это работает только потому, что вам нужно вставить одну строку в таблицу2. Если бы вам понадобилось вставить больше, этот метод не сработал бы должным образом. Я полагаю, вы могли бы использовать:

 CREATE TEMP TABLE Table3
(
    value   INTEGER NOT NULL
);

INSERT INTO Table1(Serial, Data1, Data2)
    VALUES(0, 'newdata1', 'newdata2');
INSERT INTO Table3(Value)
    VALUES(DBINFO('sqlca.sqlerrd1'));
INSERT INTO Table2(Serial, Data1, Data2)
    VALUES(0, (SELECT MAX(value) FROM Table3), 'newdata3');
INSERT INTO Table2(Serial, Data1, Data2)
    VALUES(0, (SELECT MAX(value) FROM Table3), 'newdata4');
  

И так далее…временная таблица для Table3 позволяет избежать проблем с параллелизмом и MAX().