[英]Invalid number of arguments error in oracle
請讓我知道以下查詢的插入語句中是否有錯誤。 它給我“無效數量的參數”錯誤
create or replace PROCEDURE adm_getMaxTableIdLimited
(
v_TableName IN VARCHAR2 DEFAULT NULL ,
v_TableIDColumnName IN VARCHAR2 DEFAULT NULL ,
v_MaxTableId OUT NUMBER
)
AS
v_Limit NUMBER(10,0);
v_SQLStatement VARCHAR2(255);
BEGIN
v_Limit:= 99999 ;
v_MaxTableId:= 0 ;
EXECUTE IMMEDIATE 'DROP TABLE TempResult';
EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE TempResult
(
Result NUMBER(10,0)
)';
v_SQLStatement:= 'Insert INTO TempResult(Result) SELECT max(' || v_TableIDColumnName || ')
FROM ' || v_TableName || ' WHERE ' || v_TableIDColumnName || ' <= ' || CAST(v_limit AS
VARCHAR2) || ';';
EXECUTE IMMEDIATE v_SQLStatement;
EXECUTE IMMEDIATE 'SELECT Result INTO v_MaxTableId FROM TempResult' ;
IF ( v_MaxTableId = v_Limit ) THEN
v_MaxTableId := -1 ;
ELSE
v_MaxTableId := v_MaxTableId + 1 ;
END IF;
EXECUTE IMMEDIATE ' TRUNCATE TABLE TempResult ';
END;
您根本不需要臨時表。 您的代碼可以大大簡化:
create or replace PROCEDURE adm_getMaxTableIdLimited
(
v_TableName IN VARCHAR2 DEFAULT NULL,
v_TableIDColumnName IN VARCHAR2 DEFAULT NULL,
v_MaxTableId OUT NUMBER
)
AS
v_Limit NUMBER;
BEGIN
v_Limit:= 99999 ;
EXECUTE IMMEDIATE
'SELECT MAX(' || v_TableIDColumnName || ') FROM '
|| v_TableName || ' WHERE ' || v_TableIDColumnName || ' <= :limit'
INTO v_MaxTableId
USING v_Limit;
IF v_MaxTableId = v_Limit THEN
v_MaxTableId := -1;
ELSE
v_MaxTableId := v_MaxTableId + 1;
END IF;
END;
順便說一句:您的代碼中的當前問題是:
EXECUTE IMMEDIATE 'SELECT Result INTO v_MaxTableId FROM TempResult';
正確的行是:
EXECUTE IMMEDIATE 'SELECT Result FROM TempResult' INTO v_MaxTableId;
首先,您似乎非常不可能動態刪除並創建臨時表。 全局臨時表就是全局的。 表定義對其他會話可見,這與您可能已經習慣於其他數據庫的表定義不同。 與永久表一樣,在安裝應用程序時只需創建一次臨時表。 在多用戶環境中,刪除和重新創建表將無法正常工作。
其次,似乎沒有任何理由在這里使用臨時表。 您可以僅動態生成SELECT
語句並將結果存儲在局部變量中。
第三,您的INSERT
語句末尾不應使用分號。 這就是生成ORA-00911的原因:無效字符錯誤。
第四,動態SELECT
語句不應具有INTO
。 該INTO
子句需要是EXECUTE IMMEDIATE
一部分,而不是SQL語句的一部分。
因此,我的猜測是您想要類似
create or replace PROCEDURE adm_getMaxTableIdLimited
(
v_TableName IN VARCHAR2 DEFAULT NULL ,
v_TableIDColumnName IN VARCHAR2 DEFAULT NULL ,
v_MaxTableId OUT NUMBER
)
AS
v_Limit NUMBER(10,0) := 99999;
v_SQLStatement VARCHAR2(255);
BEGIN
v_SQLStatement :=
'SELECT max(' || v_TableIDColumnName || ') ' ||
' FROM ' || v_TableName ||
' WHERE ' || v_TableIDColumnName || ' <= :1';
EXECUTE IMMEDIATE v_SQLStatement
INTO v_MaxTableId
USING v_Limit;
IF ( v_MaxTableId = v_Limit ) THEN
v_MaxTableId := -1 ;
ELSE
v_MaxTableId := v_MaxTableId + 1 ;
END IF;
結束;
但是,為什么首先要創建此過程? 它似乎用於返回要插入表中的鍵的下一個值。 如果您正在這樣做,則需要重新考慮您的方法。 與掃描序列相比,生成動態SQL掃描主鍵索引的最大值的效率要低得多。 它也不能在玩具系統之外正常工作,在玩具系統中,您可以保證只有一個用戶。 在實際系統中,多個會話將獲得相同的值,並嘗試使用相同的鍵插入行。 兩者之一將在INSERT
上阻塞,並最終得到重復的密鑰錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.