过程中的光标返回的值多于查询

问题描述 投票:0回答:2

我在接收几个参数的过程中使用简单的光标。 然后,我将光标放在带有多个条件的 where 子句的选择查询上,这些条件等于接收到的参数。该游标应该只返回 1 行,而不是返回多行。我发现这一点是因为我正在使用 for 循环来遍历此游标并根据此游标的值将某些内容插入到另一个表中。

当我静态地在数据库上运行查询时(如在没有 pl/sql 的情况下),我得到了我所期望的结果,但是当我从应该只返回一行的游标执行查询并在 for 循环中运行它时,循环确实多次迭代。这怎么可能?

谢谢!

编辑:

ID kind kolo kolo1 mjt salesman money   date       done
1  001  001  002   00013 00056  100,00  21-feb-12  N

我像这样运行光标:

Cursor linija IS 
SELECT *
FROM table_x X

where x.mjt = mjt
and   x.salesman = salesman
and x.kind = kind
and x.kolo1 = kolo1
and x.done = 'N';

这应该只返回一行,但我的光标返回 %rowcount 是 10。

sql oracle stored-procedures cursor
2个回答
2
投票

您的姓名有冲突。您已将局部变量命名为与列名称相同的名称,并且列名称优先,如文档中所述 :

如果 SQL 语句引用的名称既属于列又属于局部变量或形式参数,则列名称优先。

注意: 当变量或参数名称被解释为列名称时,数据可能会被无意中删除、更改或插入。

前四项检查始终为真(除非您有空值),因此您将获得具有

done = 'N'

 的每一行。

将局部变量名称更改为其他名称;使用前缀来区分局部变量、参数和列是相当常见的,例如:

Cursor linija IS SELECT * FROM table_x X where x.mjt = l_mjt and x.salesman = l_salesman and x.kind = l_kind and x.kolo1 = l_kolo1 and x.done = 'N';
如果这是在存储过程中,而不是在匿名块中,则可以使用过程/函数名称作为前缀,有些人更喜欢这样做。例如,如果您的程序名为 

myproc

,您可以这样做:

Cursor linija IS SELECT * FROM table_x X where x.mjt = myproc.mjt and x.salesman = myproc.salesman and x.kind = myproc.kind and x.kolo1 = myproc.kolo1 and x.done = 'N';


您还可以为光标提供自己的形式参数,并以相同的方式引用它们,并使用前缀参数名称:

Cursor linija ( p_mjt table_x.mjt%type, p_salesman table_x.salesman%type, p_kind table_x.kind%type, p_kolo1 table_x.kolo1%type ) IS SELECT * FROM table_x X where x.mjt = p_mjt and x.salesman = p_salesman and x.kind = p_kind and x.kolo1 = p_kolo1 and x.done = 'N';
或以光标名称作为前缀:

Cursor linija ( mjt table_x.mjt%type, salesman table_x.salesman%type, kind table_x.kind%type, kolo1 table_x.kolo1%type ) IS SELECT * FROM table_x X where x.mjt = linija.mjt and x.salesman = linija.salesman and x.kind = linija.kind and x.kolo1 = linija.kolo1 and x.done = 'N';
无论哪种方式,当您打开光标时都包含参数,例如如果您无论如何在过程级别更改了变量名称:

for x in linija (l_mjt, l_salesman, l_kind, l_kolo1) loop
或者如果你没有:

for x in linija (myproc.mjt, myproc.salesman, myproc.kind, myproc.kolo1) loop
    

1
投票
除了 Alex 所说的(我不能充分赞同他的建议来区分变量名和列名!),为什么要使用游标 for 循环来执行插入?

您可以只在一条 SQL 语句中进行插入,例如:

insert into your_table (col1, col2, ...) select col1, col2, ... from your_table where ...

这比遍历整个数据集并一次插入每一行要好得多。当谈到数据库时,尽可能多地考虑基于集合,而不是程序!

© www.soinside.com 2019 - 2024. All rights reserved.