提问人:Andrew 提问时间:10/11/2021 更新时间:10/11/2021 访问量:318
调用 Oracle 存储过程中的参数数量或类型错误
wrong number or types of arguments in call to Oracle stored procedure
问:
我在下面创建了 Oracle 参数化存储过程,我试图在其中将表权限授予另一个用户,但收到错误为 .Truncate
wrong number or types of arguments in call to DO_TRUNCATE
create or replace procedure "DWH_02"."DO_TRUNCATE" (truncate_tablename NVARCHAR2)
IS
begin
EXECUTE IMMEDIATE 'TRUNCATE TABLE' || truncate_tablename;
EXECUTE IMMEDIATE 'grant execute on ' || DWH_02.DO_TRUNCATE ||' TO DWH_ST';
end;
/
答:
1赞
MT0
10/11/2021
#1
语句中缺少空格字符,过程名称应位于语句的字符串文本中(而不是尝试动态追加它):TRUNCATE
GRANT
create or replace procedure "DWH_02"."DO_TRUNCATE" (truncate_tablename NVARCHAR2)
IS
begin
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || truncate_tablename;
-- ^ Here
EXECUTE IMMEDIATE 'grant execute on DWH_02.DO_TRUNCATE TO DWH_ST';
end;
/
我也不确定在程序中包括它的价值是什么。您只需要运行一次,并且可以在过程之外使用特权用户执行此操作;显然没有必要将其包含在程序中。GRANT
GRANT
评论
0赞
Andrew
10/11/2021
@MTO谢谢......实际上,我想将截断权限授予用户DWH_ST的所有表...你还有其他更好的方法来做到这一点吗?
0赞
Andrew
10/11/2021
我应该做这样的事情吗?创建或替换过程 do_truncate (truncate_tablename NVARCHAR2) as begin EXECUTE IMMEDIATE 'TRUNCATE TABLE ' ||truncate_tablename;结束;/ 执行do_truncate('TEST_TBL');
0赞
MT0
10/11/2021
@Andrew 是的,然后只需运行该过程,以授予 Alice(或任何人)运行该过程的权限。无需在每次运行该过程时重新授予该权限。或者更糟糕的是,如果该过程仍在授予权限,并且您更改了谁应该负责截断表并手动撤消该用户的权限,那么下次其他人运行该过程时,它将重新授予该权限,并且用户将有权访问他们不应该访问的内容。GRANT EXECUTE ON DWH_02.DO_TRUNCATE TO ALICE;
0赞
Andrew
10/11/2021
@MTO我不知道我以某种方式收到错误,即使我尝试以与我提到的相同的方式授予,特权不足
0赞
Andrew
10/11/2021
我知道我还需要 DROP 任何缺少的特权。.
1赞
Roberto Hernandez
10/11/2021
#2
同一解决方案的另一个版本,对如何截断表和调试以查看执行的命令有更多的控制权。
让我向您展示演示
SQL> create table test3.t1 ( c1 number, c2 number ) ;
Table created.
SQL> insert into test3.t1 select level, level from dual connect by level <= 10000 ;
10000 rows created.
然后我创建自己的截断过程
SQL> create or replace procedure test3.do_truncate ( ptablename in NVARCHAR2, poption in varchar2, pdebug in boolean default true )
2 is
3 vcount pls_integer;
4 vsql varchar2(400);
5 begin
6 vsql := 'truncate table ' || ptablename || ' ' || poption || ' storage ';
7 select count(*) into vcount from user_tables where table_name = upper(ptablename) ;
8 if vcount = 1
9 then
10 if pdebug
11 then
12 dbms_output.put_line(vsql);
13 end if;
14 execute immediate vsql;
15 else
16 raise_application_error(-20001,'Table '||ptablename||' does not exist in schema TEST3 ');
17 end if;
18* end;
Procedure created.
SQL> exec test3.do_truncate( 'T1' , 'REUSE' , true ) ;
truncate table T1 REUSE storage
PL/SQL procedure successfully completed.
SQL> exec test3.do_truncate( 'T2' , 'DROP' , true ) ;
BEGIN test3.do_truncate( 'T2' , 'DROP' , true ) ; END;
*
ERROR at line 1:
ORA-20001: Table T2 does not exist in schema TEST3
ORA-06512: at "TEST3.DO_TRUNCATE", line 16
ORA-06512: at line 1
如果您也想控制该选项
create or replace procedure test3.do_truncate ( ptablename in NVARCHAR2, poption in varchar2, pdebug in boolean default true )
is
vcount pls_integer;
vsql varchar2(400);
begin
if upper(poption) not in ('DROP','REUSE')
then
raise_application_error(-20002,'Specify DROP or REUSE for storage option in truncate');
end if;
vsql := 'truncate table ' || ptablename || ' ' || poption || ' storage ';
select count(*) into vcount from user_tables where table_name = upper(ptablename) ;
if vcount = 1
then
if pdebug
then
dbms_output.put_line(vsql);
end if;
execute immediate vsql;
else
raise_application_error(-20001,'Table '||ptablename||' does not exist in schema TEST3 ');
end if;
end;
评论
- 最好控制过程中的错误,以防截断它不存在的表。
- 正如@MTO已经解释的那样,它本身不应该在程序中。如果您要删除/创建表,这将是必要的。
GRANT
- 您可以使用两个选项进行截断
reuse storage
drop storage
指定从已删除的行中取消分配所有空间 从表中,但 MINEXTENTS 参数分配的空间除外 表或集群。此空间随后可供其他空间使用 表空间中的对象。Oracle Database 还设置 NEXT 存储 参数设置为从线段中移除的最后一个范围的大小 截断过程。这是默认设置。
DROP STORAGE
指定以保留已删除行的空间 分配给表。存储值不会重置为值 创建表或集群时。此空间随后可以 仅由表或集群中的新数据使用,这些数据由插入或 更新操作。此子句将存储参数保留在 当前设置。
REUSE STORAGE
评论