简体   繁体   English

在where子句中使用Oracle SQL变量时遇到问题

[英]Trouble using Oracle SQL variable in where clause

I'm trying to write a script to help assist with the numerous "What's happened to this actionlist" type calls, but i'm coming up against a brick wall doing some of the most simplest operations. 我正在尝试编写一个脚本来帮助解决众多“这个动作列表中发生了什么”类型的调用,但是我正在做一些砖墙做一些最简单的操作。

I'm trying to declare a variable and use it in the where clause of a query. 我正在尝试声明一个变量并在查询的where子句中使用它。 I've trimmed everything irrelevant out of the query, in an attempt to get this core functionality to work. 为了让这个核心功能发挥作用,我已经修剪了查询中不相关的所有内容。

The id is usually an 18 digit number, but does occasionally contain alpha-numerics, hence why it is a varchar. id通常是一个18位数字,但偶尔会包含alpha-numerics,因此它为varchar。 The column I'm trying to compare it to is an 18 byte varchar field. 我试图将它与之比较的列是一个18字节的varchar字段。

declare
  id_to_check VARCHAR(18);  

begin
  id_to_check := '549576015500000109';

select 
  txn_timestamp, exception_type
from cut.event
where irn_id = id_to_check;

end;

Every time it throws an error: 'an INTO clause is expected in this select statement'. 每次它抛出一个错误:'在这个select语句中需要一个INTO子句'。 I understand how INTO's work, ie if I wanted to assign the result of a select to the variable, but I don't understand how that would apply in this instance as I'm not assigning the result of the query to a variable? 我理解INTO是如何工作的,即如果我想将select的结果赋给变量,但是我不明白在这个实例中如何应用,因为我没有将查询的结果赋给变量?

The other frustrating thing is I'm actually following documentation on docs.oracle.com. 另一个令人沮丧的事情是我实际上正在关注docs.oracle.com上的文档。

http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/overview.htm#LNPLS001 . http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/overview.htm#LNPLS001

I've also looked at various google results, but I can't figure out how to do a comparison with the variable without first selecting something into it, but as you can see, I can't select into because I only need it for comparison reasons? 我也查看了各种谷歌搜索结果,但我无法弄清楚如何在没有先选择内容的情况下与变量进行比较,但正如您所看到的,我无法选择进入,因为我只需要它比较原因?

Kind Regards, Ian 亲切的问候,伊恩

Raphaël Althaus's answer applies if you are doing something in PL/SQL, but I'm not sure that's actually what you want. RaphaëlAlthaus的答案适用于你在PL / SQL中做的事情,但我不确定这实际上是你想要的。 It sounds like you want a plain SQL query, but you want to be able to pass it a value? 听起来你想要一个简单的SQL查询,但你想能够传递一个值吗? Assuming you're running this in SQL*Plus or SQL Developer you have a few ways to declare and use a fixed value. 假设您在SQL * Plus或SQL Developer中运行它,您可以通过几种方式声明和使用固定值。 (Similar methods will be available in other clients; PL/SQL developer seems to like both of these, at least in the command window, but not sure about Toad or anything else). (类似的方法将在其他客户端可用; PL / SQL开发人员似乎喜欢这两种方法,至少在命令窗口中,但不确定Toad或其他任何东西)。

1) Using a substitution variable : 1)使用替换变量

define id_to_check = 549576015500000109

select txn_timestamp, exception_type
from cut.event
where irn_id = '&id_to_check';

2) Using a bind variable : 2)使用绑定变量

variable id_to_check varchar2(18)

exec :id_to_check := '549576015500000109';

select txn_timestamp, exception_type
from cut.event
where irn_id = :id_to_check;

The exec is shorthand for a small anonymous PL/SQL block, but apart from step of assigning the value to the variable, it's plain SQL, so the query doesn't need to be wrapped in a begin ... end , and you don't have to worry about selecting into variables. exec是一个小的匿名PL / SQL块的简写,但除了将值赋给变量的步骤之外,它是纯SQL,因此查询不需要包含在begin ... end ,而且你不需要“吨担心选择into变量。

In either case you can have the ID value passed as an argument , or ask for it as part of the script , when the script it run. 在任何一种情况下,您都可以将ID值作为参数传递 ,或者在运行脚本时将其作为脚本的一部分进行请求 For example, you could write a query.sql script: 例如,您可以编写query.sql脚本:

define id_to_check = &1

select txn_timestamp, exception_type
from cut.event
where irn_id = '&id_to_check';

... and run it with: ...并运行它:

sqlplus -l -s <user>/<password> @query 549576015500000109

... or as: ......或者:

accept id_to_check prompt 'Enter the ID to check: '

select txn_timestamp, exception_type
from cut.event
where irn_id = '&id_to_check';

... and have the user prompted to enter the ID at run-time. ...并提示用户在运行时输入ID。

The question is not "Do you want to put the result into a variable". 问题不是“你想把结果放到一个变量中”。

In the "body" of an Oracle procedure, you just can't use a SELECT without an INTO clause. 在Oracle过程的“主体”中,如果没有INTO子句,则无法使用SELECT

(In fact you can have, but in a cursor). (事实上​​你可以拥有,但在游标中)。

so 所以

declare
  id_to_check VARCHAR(18);
  event_timestamp cut.event.txn_timestamp%TYPE;
  event_exception cut.event.exception_type%TYPE;

begin
  id_to_check := '549576015500000109';

select 
  txn_timestamp, exception_type
  INTO event_timestamp, event_exception
from cut.event
where irn_id = id_to_check;

end;

Caution : if no result is found, this will raise a NO_DATA_FOUND exception. 警告:如果未找到任何结果,则会引发NO_DATA_FOUND异常。

You can manage it with 你可以用它来管理它

begin
  id_to_check := '549576015500000109';

  BEGIN
  select 
    txn_timestamp, exception_type
    INTO event_timestamp, event_exception
    from cut.event
    where irn_id = id_to_check;

   EXCEPTION WHEN NO_DATA_FOUND THEN 
   --...something
  END

end

Your real problem is NOT about using variable (you got that right), but about returning cursors from PL/SQL blocks. 你真正的问题不是关于使用变量(你是否正确),而是关于从PL / SQL块返回游标。

You seem to believe that a bare select at the end of a procedure should somehow make it return the results or at least display them. 你似乎相信在程序结束时的一个裸选择应该以某种方式使它返回结果或至少显示它们。 While some databases work like that - Oracle does not. 虽然有些数据库的工作方式如此 - 但Oracle没有。 If you want any data to leave a block of any kind (like function or procedure), you have to pass them explicitly. 如果您希望任何数据留下任何类型的块(如函数或过程),则必须明确地传递它们。 Usually this is done by using an in parameter of a cursor ref type. 通常这是通过使用游标ref类型的in参数来完成的。

As you can see, the select without into would not make sense in Oracle. 正如您所看到的,没有into的select在Oracle中没有意义。 Even if you managed to make it work and select the data, you would not be able to access the results. 即使您设法使其工作并选择数据,您也无法访问结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM