将选择查询中的值插入变量

Posted

技术标签:

【中文标题】将选择查询中的值插入变量【英文标题】:Insert values from select query into variables 【发布时间】:2015-11-12 15:46:22 【问题描述】:

我正在尝试从 select 语句中插入 2 个变量值,但我收到一条错误消息:

精确提取返回的行数超过请求的行数

我猜我需要将选择查询中的数据放入某种表类型中? 但我需要处理单个记录,以便将变量 v_zmienna 与 v_zmienna2 进行比较。

如您所见,我尝试以某种方式将数据传输到 v_zmienna 和 v_zmienna2,然后比较这些值。

有人可以看看并提出最好的方法吗?

我需要使用执行立即数和变量,因为我有 Table1、Table2 表作为配置表以及应连接的表名等。

declare
c1 SYS_REFCURSOR;  
v_sourcepkcolumn varchar2(50);
v_sourcetable varchar2(50); 
v_targetfkcolumn varchar2(50); 
v_targetpkcolumn varchar2(50);    
v_targettable varchar2(50); 
v_sourcecolumn varchar2(50);  
v_targetcolumn varchar2(50); 
v_verificationdefid varchar2(50); 
v_zmienna varchar2(50); 
v_zmienna2 varchar2(50); 
v_random_number number;
begin
v_random_number := sequence1.nextval;
open c1 for select  sourcepkcolumn,
                    sourcetable,
                    targetfkcolumn,
                    targetpkcolumn,
                    targettable,
                    sourcecolumn,
                    targetcolumn,
                    ID
            from    table1,table2 where table1.ID=table2.ID;
loop
  fetch c1 into   v_sourcepkcolumn, 
                  v_sourcetable,    
                  v_targetfkcolumn, 
                  v_targetpkcolumn,   
                  v_targettable, 
                  v_sourcecolumn,    
                  v_targetcolumn, 
                  v_verificationdefid;
  exit when c1%notfound;   

  execute immediate 'select '||v_sourcetable||'.'||v_sourcecolumn||','||v_targettable||'.'||v_targetcolumn||' from '||v_sourcetable||','||v_targettable||' where '||
v_sourcetable||'.'||v_sourcepkcolumn||'='||v_targettable||'.'||v_targetfkcolumn into v_zmienna,v_zmienna2;

  if (v_zmienna=v_zmienna2) then
    execute immediate 'insert into table3 values ('||v_random_number||','||v_sourcecolumn||','||v_sourcepkcolumn||','||v_zmienna||',1,'||v_targetcolumn||','||v_targetpkcolumn||','||v_zmienna2||',timestamp,'||v_verificationdefid||')';
  else 
    execute immediate 'insert into table3 values ('||v_random_number||','||v_sourcepkcolumn||','||v_zmienna||',0,'||v_targetcolumn||','||v_targetpkcolumn||','||v_zmienna2||',timestamp,'||v_verificationdefid||')';
  end if;
end loop;
close c1;
end;

编辑:

输出

select  sourcepkcolumn,
                    sourcetable,
                    targetfkcolumn,
                    targetpkcolumn,
                    targettable,
                    sourcecolumn,
                    targetcolumn,
                  from    table1,table2 where table1.id=table2.id

看起来:

PK_ACCOUNT,ACCOUNT,PK_ACC,ID,ACCOUNT2,NAME,NAME

这是table1和table2的输出,

重要提示:帐户和帐户2 是视图!那不是 TABLES。

所以现在我不想将 account VIEW 中的 account.name 和 account2.name 与 account.pk_account=account2.pk_acc 上的 account2 VIEW 进行比较。 通常它工作得很好,但有时(取决于 oracle 顺序)在加入后 VIEW 中的记录可以是其他顺序。 例如: 帐号:

PK_ACCOUNT   NAME
1             Eva
1             Adam

和 帐号2

PK_ACCOUNT  NAME
1            Adam
1            Eva

为什么在 VIEW 中查看不同的 PK_ACCOUNT?因为我需要从多个表中插入 Account 和 Account2 数据。这就是为什么记录有时会成倍增加。

当程序对每条记录逐一处理时,将其视为发散

【问题讨论】:

在您的insert into table3 语句中,您引用了“时间戳”。您指的是 “systimestamp” 吗?此外,您的第二个插入语句只插入 9 个值,但您的第一个插入是插入 10 个。table3 中有多少列? 【参考方案1】:

我认为您可以将其重写为:

declare
  v_random_number number;
begin
  v_random_number := sequence1.nextval;
  for rec in (select  sourcepkcolumn,
                      sourcetable,
                      targetfkcolumn,
                      targetpkcolumn,
                      targettable,
                      sourcecolumn,
                      targetcolumn,
                      ID
              from    table1
                      inner join table2 on (table1.ID = table2.ID))
  loop
    execute immediate 'insert into table3 '||chr(10)|| -- where is the list of columns to insert into?!
                      ' select :v_random_number random_number,'||chr(10)||
                      '        :v_sourcecolumn source_col,'||chr(10)||
                      '        :v_sourcepkcolumn source_pk_col,'||chr(10)||
                      '        src.'||v_sourcecolumn||' source_col,'||chr(10)||
                      '        case when src.'||v_sourcecolumn||' = tgt.'||v_targetcolumn||' then 1 else 0 end one_or_zero'||chr(10)||
                      '        :v_targetcolumn target_col'||chr(10)||
                      '        :v_targetpkcolumn target_pk_col'||chr(10)||
                      '        tgt.'||v_targetcolumn||' target_col,'||chr(10)||
                      '        systimestamp tstamp,'||chr(10)||
                      '        :v_verificationdefid'||chr(10)||
                      ' from   '||v_sourcetable||' src'||chr(10)||
                      '        inner join '||v_targettable||' tgt on (src.'||v_sourcepkcolumn||' = tgt.'||v_targetfkcolumn||')'
                      using v_random_number,
                            rec.sourcecolumn,
                            rec.sourcepkcolumn,
                            rec.targetcolumn,
                            rec.targetpkcolumn,
                            rec.id;
  end loop;
end;
/

注意未经测试。我猜你的第二个插入语句缺少源列,所以我添加了。

【讨论】:

您好,感谢您的回复,我差不多完成了,但现在我有其他问题。如果我在表 1、表 2 中定义的表在加入后返回 2 条 ID 相同但顺序不同的记录怎么办?例如 1 'Smth' 1 'Smthelse' 和第二个表返回 1 'Smthelse' 1 'Smth'。 (当然 1 作为 ID)我不能将订单放入(插入语句),那么有什么解决方案吗?如果发生这样的事情,那么程序返回 0 但应该返回 1,因为这 2 条记录是相同的.. 听起来你的 table1 和 table2 之间的连接条件需要更新,因为目前,如果每个 id 有两条记录,基于现有连接,你最终会得到每个 id 4 行桌子。也许您正在基于 id 和 sourcecolumn 或其他东西进行完全外部连接? 例如,我需要比较来自 2 个不同环境的 2 个 ACCOUNTS 表,因此我将拥有例如: Account1 ID:1 但我需要将其与例如连接。表订单:PK:1 FK:1 产品:香蕉 PK:2 FK1 产品:手机和第二环境中的表:Accounts2 ID:1 表订单:PK:1 FK:1 订单:香蕉 PK:2 FK1 订单:手机现在,当我通过订单加入帐户时,我将获得:1 部香蕉 1 部手机,有时(取决于 oracle ...)当我通过订单加入帐户 2 时,我将获得:1 部手机 1 部香蕉 所以对于记录不同的过程......我所要做的就是以某种方式订购这些数据......但我不知道如何 请更新您的问题以添加表 1 和 2 中的数据,以及您期望的输出。这样,我们就有更好的机会为您提供帮助。【参考方案2】:

您得到的错误表明该语句返回多行

execute immediate 'select '||v_sourcetable||'.'||v_sourcecolumn||','||v_targettable||'.'||v_targetcolumn||' from '||v_sourcetable||','||v_targettable||' where '||
v_sourcetable||'.'||v_sourcepkcolumn||'='||v_targettable||'.'||v_targetfkcolumn into v_zmienna,v_zmienna2;

您有不止一种方法可以解决这个问题,具体取决于您可能选择的目标。

我推荐的方法是稍微改变一下方法。您可以使用不同的方法,而不是选择一组变量、比较它们并根据变量做不同的事情。首先,将满足动态条件的所有行插入到 table3 中。然后,将不满足动态条件的所有行插入到 table3 中。这将是这样的:

execute immediate 'insert into table3 values ('||v_random_number||','||v_sourcecolumn||','||v_sourcepkcolumn||','||v_zmienna||',1,'||v_targetcolumn||','||v_targetpkcolumn||','||v_zmienna2||',timestamp,'||v_verificationdefid||') ' ||
' select '||v_sourcetable||'.'||v_sourcecolumn||','||v_targettable||'.'||v_targetcolumn||' from '||v_sourcetable||','||v_targettable||' where '||
v_sourcetable||'.'||v_sourcepkcolumn||'='||v_targettable||'.'||v_targetfkcolumn );

execute immediate 'insert into table3 values ('||v_random_number||','||v_sourcepkcolumn||','||v_zmienna||',0,'||v_targetcolumn||','||v_targetpkcolumn||','||v_zmienna2||',timestamp,'||v_verificationdefid||' ||
' select '||v_sourcetable||'.'||v_sourcecolumn||','||v_targettable||'.'||v_targetcolumn||' from '||v_sourcetable||','||v_targettable||' where '||
v_sourcetable||'.'||v_sourcepkcolumn||'<>'||v_targettable||'.'||v_targetfkcolumn );

您的第二个选择是与以前基本相同的方式,但在动态部分和固定部分使用游标。我不会尝试为此创建源代码,但这意味着您需要为动态选择查询创建一个游标并在游标循环中执行“if”部分

【讨论】:

还有一些其他的发生。例如,表 1、表 2 中定义的表在连接后返回 2 个具有相同 ID 但顺序不同的记录。例如 ID:1 , 'Smth' , 1 ,'Smthelse' 和 sourcetable: ID: 1: 'Smthelse, 1:'Smth' 比较后我得到状态 0 这意味着记录不一样但它是不对。我无法将 order by into (insert into statement) - 还有其他解决方案可以处理吗? @maciek2791:我不确定您指的是什么,但在我看来,您的源表中有两行具有相同的 ID (1) 但不同的值(Smth vs Smthelse )。这意味着您的 ID 不是该表中的主键。如果您对 table3 有一个约束,要求源表将 ID 作为主键,那将不起作用。我不太了解这里的业务问题,也许您可​​以描述一下以便更好地回答

以上是关于将选择查询中的值插入变量的主要内容,如果未能解决你的问题,请参考以下文章

如何在表中插入变量(@id)作为 SQL 服务器查询中的自动增量?

如何将 HTML 作为 PostgreSQL 插入查询中的值处理?

如何分解数据库中的值并在选择查询中使用它?

如何从具有动态分区的选择查询中插入 Hive 中的列?

有没有办法将此插入合并到选择查询中?

MYSQL如何根据变量的值来选择字段进行查询