如何在多个insert语句中生成变量名?

时间:2016-03-11 14:39:31

标签: stored-procedures informix

我有18对不同的表列名称,如:

name_1, surname_1, ... name_18, surname_18

我想用以下内容生成18个Informix SPL插件:

define _counter Int;
define _name_1 varchar(20);
define _surname_1 varchar(20);
...
define _name_18 varchar(20);
define _surname varchar(20);

select  name_1,  surname_1, ...,  name_18,  surname_18
  into _name_1, _surname_1, ..., _name_18, _surname_18
  from names where name_id = 1;

for _counter = 1 to 18 loop 
  insert into person(name, surname) values (_name_+_counter,   _surname_+_counter);
end loop 

如果我试试这个,我会收到语法错误。我被困在可怕的桌子设计中。你能否告诉我们是否有类似/正确的方法来完成这项工作?

2 个答案:

答案 0 :(得分:1)

鉴于问题的轮廓更清晰,我认为你必须放弃循环。您可以做的最好的是18个连续的INSERT语句,或18个对每次调用执行一个语句的存储过程的调用。

Informix SPL没有数组类型,您只能将循环与数组一起使用。 (我已经看到内部带有CASE语句的循环,循环的每次迭代都有一个案例;它们很少能很好地解决问题,而且对于这种情况来说这不是一个明智的解决方案。)

我将重复我先前评论中的一个观察结果:具有18对柱的表的设计非常不理想。但是,您似乎正在尝试将数据从此次优模式传输到更合理的模式,每个名称只有一行。

您还可以考虑使用18路UNION:

 INSERT INTO Person(Name, Surname)
     SELECT Name_1,  Surname_1  FROM Names -- WHERE name_id = 1
     UNION
     SELECT Name_2,  Surname_2  FROM Names -- …
     UNION …
     SELECT Name_18, Surname_18 FROM Names -- …

如果要求确实只有name_id = 1行,则需要将该标准添加到UNION SELECT语句中的18个SELECT子句中的每一个。还有其他方法可以添加该过滤条件,在源代码级别使用不同的权衡集(并且可能在优化器中进行不同的权衡)。 Informix(尚未)支持CTE(公用表表达式,又名WITH子句),这在这种情况下很可惜。

请注意,显示的代码在一个SQL语句中将所有数据从Names传输到Person。这可能是最接近最佳整体流程的。

答案 1 :(得分:0)

也许这样的东西就是你想要的(使用informix 12.10FC6,不确定它是否适用于以前的版本):

CREATE PROCEDURE copy_paste_names (p_name_id INTEGER);

    DEFINE 
        l_query_string VARCHAR(255);  
    DEFINE
        iter INT;

    FOR iter IN (1 TO 18 STEP 1)
        LET l_query_string = 'INSERT INTO person (name, surname) SELECT name_' || iter || ', surname_' || iter || ' FROM names WHERE name_id = ' || p_name_id || ';';
        EXECUTE IMMEDIATE l_query_string;
    END FOR;      

END PROCEDURE;

我假设names表总是有18对名为name_?surname_?的列。

此过程只是盲目地尝试将name_?表中的每对surname_?names列复制到person表中的新行。没有任何类型的检查来查看是否实际存在要复制的值或是否