暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 很少的SQL & PL/SQL问题

askTom 2018-01-17
300

问题描述

嗨,
这里面有三个小问题,我12月想问,但是你们在度假,这就是为什么我不能问。

Q1. 什么是触发器的确切大小限制我已经阅读32k这里是什么是KB或 (32000字节或32768字节),如果它KB,那么我已经创建了一个触发器超过这个字节,但oracle没有反对。请以字节为单位告诉准确的数字。

Q2. 参考光标相关问题

PROMPT CREATING THE TABLE... DELME BACKUP ON FRIDAY, 08-DEC-2017 02:43:24 AM

CREATE TABLE DELME
(
ID                              NUMBER,
NAME                            VARCHAR2(30)
)
/
PROMPT INSERTING INTO THE TABLE... DELME

Insert Into Delme
Values('101','Ankur')
/
Insert Into Delme
Values('102','Kumar')
/
Insert Into Delme
Values('103','Thakran')
/
Insert Into Delme
Values('104','Danny')
/
Insert Into Delme
Values('105','Danger')
/
Commit
/

--Block-1--
declare
type rct is ref cursor;
rc rct;
rec delme%rowtype;
begin
open rc for
'
select *
from delme
where id = nvl(:Id, id)
'
using Null--When I am passing NULL like this then this block is raising error.
;
loop
 fetch rc
 into rec;
 exit when rc%notfound or rc%notfound is null;
 print(rec.Id||' ' ||rec.name);
end loop;
close rc;
end;
/

--Block-2--
declare
type rct is ref cursor;
rc rct;
rec delme%rowtype;
begin
open rc for
'
select *
from delme
where id = nvl(:Id, id)
'
using ''--But when I call this block using '' then it is executing as expected while null and '' both are same please explain why the above program is not working.
;
loop
 fetch rc
 into rec;
 exit when rc%notfound or rc%notfound is null;
 print(rec.Id||' ' ||rec.name);
end loop;
close rc;
end;
/


-我已经在Oracle 10.2.0.3.0上测试了此代码-

在块1中,当我通过using子句传递NULL时,此块引发错误。但是
在块2中,当我通过使用子句传递 ''然后这个块按照我的预期执行。

我的问题是,null和 ''都代表NULL,那么为什么这两个块的执行不同。是一种虫子吗?

Q3. 当我运行

select *
from delme
union all
select empno, ename
from emp
order by name
/


它引发错误 (ORA-00904: “名称”: 无效标识符)

但是当我跑步的时候

select id, name
from delme
union all
select empno, ename
from emp
order by name
/


它的执行没有问题,在第一个查询中,我使用 * 而在第二个查询中,我编写了列名,oracle不能解决自己的列名吗?

专家解答

1.您可以创建具有明显长于32k的文本的触发器:

create table t (
  x int
);

declare
  stmt clob;
begin
  dbms_lob.createtemporary(stmt,true);
  
  stmt := 'create or replace trigger trg
  before insert on t
  for each row
begin
';

  for i in 1 .. 4 loop
    dbms_lob.writeappend(stmt, 20026, 'dbms_output.put_line(''' || lpad(i, 20000, 'x') || ''');
');
  end loop;
  
  dbms_lob.writeappend(stmt, 4, 'end;');
  
  execute immediate stmt;
  
  dbms_lob.freetemporary(stmt);
end;
/
sho err

select sum(length(text))
from   user_source
where  name = 'TRG';

SUM(LENGTH(TEXT))   
              80162 

select status from user_objects
where  object_name = 'TRG';

STATUS   
VALID


但是,实际上,如果您在触发器中获得接近32k的代码,那么您做错了!如果你must在触发器中做某事将代码放入包中。然后在触发器中调用它。

2.这是一个记录的限制:

bind_argument cannot be the reserved word NULL.

https://docs.oracle.com/en/database/oracle/oracle-database/12.2/lnpls/OPEN-FOR-statement.html#GUID-EB7AF439-FDD3-4461-9E3F-B621E8ABFB96

正如文档所建议的那样,解决方法是使用未初始化的变量:

declare
  type rct is ref cursor;
  rc    rct;
  rec   delme%rowtype;
  nul   delme.id%type;
begin
  open rc for '
select *
from delme
where id = nvl(:Id, id)' using nul;

  loop
    fetch rc into rec;
    exit when rc%notfound or rc%notfound is null;
    dbms_output.put_line( rec.id || ' ' || rec.name );
  end loop;

  close rc;
end;
/

101 Ankur
102 Kumar
103 Thakran
104 Danny
105 Danger


3.那看起来像个虫子。虽然选择 * 是你无论如何都应该避免的事情!想想如果有人在delme中添加一列会发生什么...
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论