【问题标题】:Oracle SQL - PLS-00049 - bad bind variableOracle SQL - PLS-00049 - 绑定变量错误
【发布时间】:2015-08-09 09:57:14
【问题描述】:

我有这样定义的表:

create table "nakup"  (
   "cislo_n"            INTEGER                         not null,
   "id_zak"             INTEGER                         not null,
   "jm_pobocky"         CHAR(15)                        not null,
   "datum_cas"          DATE                            not null
      constraint CKC_DATUM_CAS_NAKUP check ("datum_cas" >= TO_DATE('1.01.1994 8:30:25', 'DD.MM.YYYY HH24:MI:SS')),
   constraint PK_NAKUP primary key ("cislo_n")

我想创建一个触发器来阻止插入未来的日期,我的代码如下所示:

create or replace TRIGGER TRIGGER1 
BEFORE INSERT OR UPDATE ON "nakup" 
FOR EACH ROW 
BEGIN
  if (:new.datum_cas > current_timestamp) then
  raise_application_error(-20000, 'Špatně zadané datum a čas.');
end if;
END;

我不断收到错误 Error(5,7): PLS-00049: chybná vázaná proměnná 'NEW.DATUM_CAS'(英语中的绑定变量错误)。我做错了什么?

【问题讨论】:

  • 使用:new."datum_cas"是否有效?
  • Quoted identifiers 会给你带来痛苦,Oracle 不推荐使用它们;除非您有真正充分的理由,否则请使用不带引号的标识符。
  • "datum_cas" 是与 datum_cas 不同的列名,在 Oracle 手册的“SQL 的基本元素”一章中有说明:docs.oracle.com/cd/E11882_01/server.112/e41084/…
  • 没有理由使用datum_cas 作为带引号的标识符。好的做法是使用不带引号的标识符。见stackoverflow.com/a/30457938/3989608带引号的标识符 在您引用该对象时使用双引号。如果您使用双引号创建对象,则它会区分大小写,并且无论在何处引用该对象,都必须始终以相同的方式使用。
  • 另外,1.避免使用CHAR,使用VARCHAR2。 2.datum_casDATE数据类型,但是比较的是current_timestamp

标签: sql oracle plsql database-trigger


【解决方案1】:

正如 Gordon Linoff 所建议的,如果您将列名括在双引号中,您的触发器将编译:

create or replace TRIGGER TRIGGER1 
BEFORE INSERT OR UPDATE ON "nakup" 
FOR EACH ROW 
BEGIN
  if (:new."datum_cas" > current_timestamp) then
  raise_application_error(-20000, 'Špatně zadané datum a čas.');
end if;
END;
/

Trigger TRIGGER1 compiled

Quoted identifiers 在被引用的任何地方都必须被引用。您似乎已经意识到,当您在触发器定义中引用表名时,它也适用于列名。

如果您使用不带引号的标识符(或带引号的大写标识符,只要它们不包含任何无效字符,那么您的生活会简单得多)。 Oracle 不建议对数据库对象名称使用带引号的标识符。所以这完全不需要双引号:

create table nakup  (
   cislo_n            INTEGER                         not null,
   id_zak             INTEGER                         not null,
   jm_pobocky         CHAR(15)                        not null,
   datum_cas          DATE                            not null,
   constraint CKC_DATUM_CAS_NAKUP
     check (datum_cas >= TO_DATE('1.01.1994 8:30:25', 'DD.MM.YYYY HH24:MI:SS')),
   constraint PK_NAKUP primary key (cislo_n)
);

Table NAKUP created.

create or replace TRIGGER TRIGGER1 
BEFORE INSERT OR UPDATE ON nakup
FOR EACH ROW 
BEGIN
  if (:new.datum_cas > current_timestamp) then
  raise_application_error(-20000, 'Špatně zadané datum a čas.');
end if;
END;
/

Trigger TRIGGER1 compiled

然后您可以在代码中引用nakup.datum_cas 等,而不必使用"nakup"."datum_cas"

【讨论】:

  • 好答案。另一个观察结果是,1. OP 使用CHAR 而不是VARCHAR2。 2.datum_casDATE数据类型,但是比较的是current_timestamp
【解决方案2】:

是的……

datum_cas 列名与datum_cas 列名不同..

Oracle默认将列名存储为大写,如果我们使用双引号(“”),则列名按原样存储(大写/小写)

例子....

SQL> create table test5 (id number,"id1" number);
      table created.

SQL> insert into  test5 values(1,2);

 1 row created.

SQL> select * from  test5;

  ID        id1
----- ----------
    1          2

id 存储为 ID,id1 存储为 id1。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-16
    • 2019-06-05
    • 2020-10-22
    • 2022-06-13
    相关资源
    最近更新 更多