我使用以下存储过程返回特定关键字的递增键值。它采用Y或N的可选参数来确定结果是否应该以另一个值作为前缀。
create or replace
PROCEDURE "ASGETPRIMARYKEY"
(
p_ObjectName IN LASTPRIMARYKEY.OBJECTNAME%type ,
p_PrimaryKey OUT LASTPRIMARYKEY.NEXTKEY%type,
useSitePrefix IN NVARCHAR2 Default 'Y'
)
AS
v_transcount NUMBER := 1;
v_sys_error NUMBER := 0;
v_SitePrefix NVARCHAR2(4000);
v_LastPrimaryKey NUMBER(10,0);
-- Error Handling Variables
v_LocalTran NUMBER(1,0);
v_Error NUMBER(10,0);
BEGIN
NULL/*TODO:SET XACT_ABORT ON*/;
NULL/*TODO:SET NOCOUNT ON*/;
-- STEP 0: Start the transaction
-- If procedure doesn't need to begin a transaction this can be set to 0
IF v_transcount > 0 THEN
v_LocalTran := 0;
ELSE
v_LocalTran := 1;
END IF;
IF v_LocalTran = 1 THEN
SET TRANSACTION READ WRITE;
v_transcount := v_transcount + 1;
END IF;
-- STEP 1: Get @SitePrefix
SELECT settingtext
INTO v_SitePrefix
FROM systemsetting
WHERE settingdescription = 'Site Id Prefix';
-- Check if there were any errors
v_Error := v_sys_error;
IF v_Error != 0 THEN
BEGIN
raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(1a)' || cast(v_error as NVARCHAR2));
GOTO ErrExit;
END;
END IF;
-- STEP 1b: Check SitePrefix exists
-- Rollback the transaction if SitePrefix doesn't exist in systemsetting
IF v_SitePrefix IS NULL THEN
BEGIN
raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(1b)' || cast(v_error as NVARCHAR2));
GOTO ErrExit;
END;
END IF;
BEGIN
-- STEP 2: Set NextKey for requested ObjectName
UPDATE LastPrimaryKey
SET NextKey = (NextKey + 1)
WHERE objectname = p_ObjectName;
EXCEPTION
WHEN OTHERS THEN
v_sys_error := SQLCODE;
END;
BEGIN
-- Check if there were any errors
v_Error := v_sys_error;
EXCEPTION
WHEN OTHERS THEN
v_sys_error := SQLCODE;
END;
IF v_Error != 0 THEN
BEGIN
raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(2)' || cast(v_error as NVARCHAR2));
GOTO ErrExit;
END;
END IF;
-- STEP 3: Set NextKey for for requested ObjectName
SELECT NextKey - 1
INTO v_LastPrimaryKey
FROM LastPrimaryKey
WHERE objectname = p_ObjectName;
BEGIN
-- Check if there were any errors
v_Error := v_sys_error;
EXCEPTION
WHEN OTHERS THEN
v_sys_error := SQLCODE;
END;
IF v_Error != 0 THEN
BEGIN
raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(3)' || cast(v_error as NVARCHAR2));
GOTO ErrExit;
END;
END IF;
-- STEP 4: Check SitePrefix exists
-- Rollback the transaction if SitePrefix doesn't exist in systemsetting
IF v_LastPrimaryKey IS NULL THEN
BEGIN
raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(4)' || cast(v_error as NVARCHAR2));
GOTO ErrExit;
END;
END IF;
-- STEP 5: Set @p_PrimaryKey by adding prefix
IF useSitePrefix = 'y' THEN
p_PrimaryKey := (CAST(v_SitePrefix || CAST(v_LastPrimaryKey AS NVARCHAR2) AS NUMBER));
ELSE
p_PrimaryKey := v_lastprimarykey;
END IF;
-- Check if there were any errors
v_Error := v_sys_error;
IF v_Error != 0 THEN
BEGIN
raise_application_error( -20002, 'Error whilst processing GetPrimaryKey.(5)' || cast(v_error as NVARCHAR2));
GOTO ErrExit;
END;
END IF;
-- STEP 6: If we reach this point, the commands completed successfully
-- Commit the transaction....
-- Normal exit
IF v_LocalTran = 1 THEN
COMMIT;
v_transcount := v_transcount - 1;
END IF;
-- Error Exit
<<ErrExit>>
IF v_LocalTran = 1 THEN
ROLLBACK;
v_transcount := v_transcount - 1;
END IF;
END;
使用以下vb代码从企业库中调用存储过程:
Dim sqlCommand As String = "asGetPrimaryKey"
Dim _db As Database = EnterpriseLibraryContainer.Current.GetInstance(Of Database)(ASDBMSS.clsDBMSS.ConnectionStringName)
Dim DbCommand As System.Data.Common.DbCommand = _db.GetStoredProcCommand(sqlCommand)
' Add primary keys to command wrapper.
_db.AddInParameter(DbCommand, "p_objectName", DbType.String, ObjectName)
If pbIgnoreSiteIndex Then
_db.AddInParameter(DbCommand, "useSitePrefix", DbType.String, "Y")
Else
_db.AddInParameter(DbCommand, "useSitePrefix", DbType.String, "N")
End If
_db.AddOutParameter(DbCommand, "p_PrimaryKey", DbType.Int32, 8)
_db.ExecuteNonQuery(DbCommand)
Dim _result As String = _db.GetParameterValue(DbCommand, "p_PrimaryKey").ToString
lcl_NextKey = CInt(_result)
result = 1
当我传递可选参数时,问题就出现了。 如果我跳过带有可选参数的行,它可以正常工作。 如果我使用SQL服务器而不是Oracle,它可以正常工作。 如果我传递参数并使用Oracle,我会收到以下错误消息:
ORA-06502:PL / SQL:数字或值错误:字符串缓冲区太小 ORA-06512:第1行
有什么建议吗?
答案 0 :(得分:1)
将v_LastPrimaryKey从数字(10,0)更改为与p_PrimaryKey相同OUT LASTPRIMARYKEY.NEXTKEY%type,
其次,你传递的是Y或N,但在代码中比较y。因此,流量总是在“其他”中进行,您不使用强制转换。 希望有所帮助。 干杯 V
答案 1 :(得分:1)
我找到了问题!
只要名称匹配,SQL服务器就不关心参数的传递顺序。看起来似乎是Oracle。
我将调用它们的顺序改为:
_db.AddInParameter(DbCommand, "p_objectName", DbType.String, ObjectName)
_db.AddOutParameter(DbCommand, "p_PrimaryKey", DbType.Int32, 8)
If pbIgnoreSiteIndex Then
_db.AddInParameter(DbCommand, "useSitePrefix", DbType.String, "Y")
Else
_db.AddInParameter(DbCommand, "useSitePrefix", DbType.String, "N")
End If
_db.ExecuteNonQuery(DbCommand)
它现在可以正常运行