2015-02-10 196 views
0

请有人帮助一个很新手的Oracle人。我在Oracle中创建了一个存储过程来删除日期范围分区。我用来创建程序的代码是:Oracle sql存储过程数据参数丢失单引号

SQL> CREATE OR REPLACE PROCEDURE NEW_EVENT_DELETE(palterdate in VARCHAR2) AS 
    2 begin 
    3 execute immediate 'ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE(palterdate, ''DD-MON-YYYY'')) UPDATE INDEXES'; 
    4 end NEW_EVENT_DELETE; 
    5/

编译没有问题,但是当我尝试使用运行程序:

ERROR at line 1: 
ORA-14755: Invalid partition specification for FOR VALUES clause. 
ORA-06512: at "ROSUSER.NEW_EVENT_DELETE", line 3 
ORA-06512: at line 1 

exec NEW_EVENT_DELETE('03-FEB-2014'); 

它回来如果我使用命令:

ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE('03-FEB-2014', 'DD-MON-YYYY')); 

然后它工作。在我看来,输入日期周围的单引号集正在丢失,因为如果我试图在日期周围没有引号的情况下运行ALTER命令,那么它就是我得到的同样的错误消息。

任何想法我做错了什么?

感谢您的任何帮助

+0

尝试NEW_EVENT_DELETE(“03-FEB-2014”);而不是单个'' – Unlockedluca 2015-02-10 15:37:50

+1

@Unlockedluca:Oracle不会使用这样的双引号。单引号是正确的。 – Ditto 2015-02-10 15:40:29

回答

0

如果你把这样的引号?

1 CREATE OR REPLACE PROCEDURE NEW_EVENT_DELETE(palterdate in VARCHAR2) AS 
2 begin 
3 execute immediate 'ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE('''||palterdate||''', ''DD-MON-YYYY'')) UPDATE INDEXES'; 
4 end NEW_EVENT_DELETE; 
5/

解释:为什么3个引号?一个逃避另一个和最后一个串联

编辑:对不起,我用'+'连接,因为我认为它是在SQl服务器上,你必须使用'||'运营商

+1

谢谢,所有。使用'''|| palterdate ||''',它的工作非常出色!再次感谢 – 2015-02-11 16:22:29

1

您没有正确传递palterdate在立即执行。将其更改为:

execute immediate 'ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE('''||palterdate||''', ''DD-MON-YYYY'')) UPDATE INDEXES' 

尽管您需要考虑有关sql注入的问题,因为此代码可能会被劫持。

+0

回复:sql注入 - 这只取决于传入日期的来源。如果它是在某个计划的批处理例程中计算的,那么sql注入极不可能是一个问题(即没有用户输入)。但是,是的,任何时候如果你用动态sql搞砸了,你必须给出一些想法。 ;)(因此,如果可能的话,避免动态sql) – Ditto 2015-02-10 15:52:42

2

当报价行情打交道,我一直喜欢这种格式:

execute immediate q'[ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE(']' || palterdate || q'[', 'DD-MON-YYYY')) UPDATE INDEXES]'; 

甚至:

lv_sql := q'[ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE('<palterdate>', 'DD-MON-YYYY')) UPDATE INDEXES]'; 
    lv_sql := REPLACE(lv_sql, '<palterdate>', palterdate); 
    execute immediate lv_sql; 
1

或者,看看使用选项执行即时

execute immediate 'ALTER TABLE ROSUSER.EVENT DROP PARTITION FOR(TO_DATE(:palterdate, ''DD-MON-YYYY'')) UPDATE INDEXES' USING palterdate; 

而且,对于SQL注入问题,快速检查palterdate可能会解决大多数问题。很难在11个字符中嵌入额外的语句! ;)