请帮我查一下这个查询有什么问题。以下是Oracle过程的代码片段。
create or replace PROCEDURE sp_Insert_ProfileStatus(
APP_EXT_CODE IN PROFILE_STATUS.APP_EXT_CODE%TYPE,
ZONE_ENV_CODE IN PROFILE_STATUS.ZONE_ENV_CODE%TYPE,
VERSION_NUMBER IN PROFILE_STATUS.VERSION_NUMBER%TYPE,
DEPLOY_STATUS IN PROFILE_STATUS.DEPLOY_STATUS%TYPE
)
IS
tmpCnt number;
tmp_query_str varchar2(2000);
BEGIN
tmp_query_str := 'select count(*) FROM PROFILE_STATUS WHERE APP_EXT_CODE =:1 '||
' AND ZONE_ENV_CODE =:2 AND VERSION_NUMBER =:3';
EXECUTE IMMEDIATE tmp_query_str
INTO tmpCnt
USING APP_EXT_CODE,ZONE_ENV_CODE,VERSION_NUMBER;
dbms_output.put_line('count:'||tmpCnt);
IF tmpCnt > 0 THEN
tmp_query_str := 'UPDATE PROFILE_STATUS SET DEPLOY_STATUS =:4 WHERE APP_EXT_CODE =:1 '||
' AND ZONE_ENV_CODE =:2 AND VERSION_NUMBER =:3';
EXECUTE IMMEDIATE tmp_query_str
USING APP_EXT_CODE,ZONE_ENV_CODE,VERSION_NUMBER,DEPLOY_STATUS;
ELSE
tmp_query_str := 'INSERT INTO PROFILE_STATUS(WPS_ID,APP_EXT_CODE,ZONE_ENV_CODE,'||
'VERSION_NUMBER,DEPLOY_STATUS)'||
'VALUES(SYS_GUID(),:1,:2,:3,:4)';
EXECUTE IMMEDIATE tmp_query_str
USING APP_EXT_CODE,ZONE_ENV_CODE,VERSION_NUMBER,DEPLOY_STATUS;
END IF;
执行程序:
EXEC sp_Insert_ProfileStatus('APP1','PROD','1.0.1','i');result ---count:1, one row is inserted.
EXEC sp_Insert_ProfileStatus('APP1','PROD','1.0.1','u');result ---count:1, no row is affected.
更新:
create or replace PROCEDURE sp_Insert_ProfileStatus(
APP_EXT_CODE IN PROFILE_STATUS.APP_EXT_CODE%TYPE,
ZONE_ENV_CODE IN PROFILE_STATUS.ZONE_ENV_CODE%TYPE,
VERSION_NUMBER IN PROFILE_STATUS.VERSION_NUMBER%TYPE,
DEPLOY_STATUS IN PROFILE_STATUS.DEPLOY_STATUS%TYPE
)
IS
tmpCnt number;
BEGIN
SELECT COUNT(*) INTO tmpCnt FROM WAF1_PROFILE_STATUS WHERE APP_EXT_CODE =APP_EXT_CODE
AND ZONE_ENV_CODE =ZONE_ENV_CODE AND VERSION_NUMBER =VERSION_NUMBER;
dbms_output.put_line('count:'||tmpCnt);
IF tmpCnt > 0 THEN
UPDATE WAF1_PROFILE_STATUS SET DEPLOY_STATUS =DEPLOY_STATUS WHERE APP_EXT_CODE =APP_EXT_CODE
AND ZONE_ENV_CODE =ZONE_ENV_CODE AND VERSION_NUMBER =VERSION_NUMBER;
ELSE
INSERT INTO WAF1_PROFILE_STATUS(WPS_ID,APP_EXT_CODE,ZONE_ENV_CODE,VERSION_NUMBER,DEPLOY_STATUS)
VALUES(SYS_GUID(),APP_EXT_CODE,ZONE_ENV_CODE,VERSION_NUMBER,DEPLOY_STATUS);
END IF;
END sp_Insert_ProfileStatus;
这里的第二部分 count 来了,但没有发生更新。请帮我找到问题。
答案 0 :(得分:1)
当您说update isnt happening
表示错误时?在这种情况下,您应该发布该错误。
在任何情况下都不要将您的变量命名为字段名称。其他明智的你说set a = a
UPDATE WAF1_PROFILE_STATUS
SET DEPLOY_STATUS = DEPLOY_STATUS
WHERE
APP_EXT_CODE = APP_EXT_CODE
AND ZONE_ENV_CODE = ZONE_ENV_CODE
AND VERSION_NUMBER = VERSION_NUMBER;
使用类似的东西来识别变量或字段。使用你喜欢的任何符号。
UPDATE WAF1_PROFILE_STATUS
SET DEPLOY_STATUS = i_DEPLOY_STATUS
WHERE
APP_EXT_CODE = i_APP_EXT_CODE
AND ZONE_ENV_CODE = i_ZONE_ENV_CODE
AND VERSION_NUMBER = i_iVERSION_NUMBER;
答案 1 :(得分:0)
您的代码中存在一些不同的问题。
首先,没有理由使用动态SQL。如果在编译时不知道要执行的SQL语句,那么您只使用动态SQL - 例如,如果您需要确定在运行时更新哪个表。在设计良好的应用程序中,您几乎不需要动态SQL。
如果您要使用动态SQL,则update
语句没有意义。 using
子句中的值按照它们在语句中出现的顺序绑定到各种绑定变量,而不是基于绑定变量的名称。
tmp_query_str := 'UPDATE PROFILE_STATUS SET DEPLOY_STATUS =:4 WHERE APP_EXT_CODE =:1 '||
' AND ZONE_ENV_CODE =:2 AND VERSION_NUMBER =:3';
EXECUTE IMMEDIATE tmp_query_str
USING APP_EXT_CODE,ZONE_ENV_CODE,VERSION_NUMBER,DEPLOY_STATUS;
因此,例如,当您说set deploy_status = :4
但这是语句中的第一个绑定变量时,会从using
子句中分配您传入的第一个值。在这种情况下,您要将deploy_status
设置为app_ext_code
中的值,您的where
子句会将app_ext_code
列中的值与该值中的值进行比较zone_env_code
参数等
如果您出于某种原因要使用动态SQL,则需要在using
子句中以正确的顺序指定参数
EXECUTE IMMEDIATE tmp_query_str
USING deploy_status, APP_EXT_CODE,ZONE_ENV_CODE,VERSION_NUMBER;
但是,就像我说的那样,当静态SQL完成工作时,在这里使用动态SQL没有任何意义。但是,当您摆脱动态SQL时,您遇到的问题是您的参数名称可能选择不当。大多数开发人员和项目确保参数和本地变量不共享数据库列的名称,否则通常会导致名称解析问题。
在你的第二个例子中,你写的是
UPDATE WAF1_PROFILE_STATUS
SET DEPLOY_STATUS =DEPLOY_STATUS
WHERE APP_EXT_CODE =APP_EXT_CODE
AND ZONE_ENV_CODE =ZONE_ENV_CODE
AND VERSION_NUMBER =VERSION_NUMBER;
您的目标可能是将app_ext_code
列中的数据与作为app_ext_code
参数传入的值进行比较。但那不是你的代码所做的。相反,两个app_ext_code
引用都解析为表中的列而不是参数。实际上,您的更新实际上是更新表中的每一行,只是将deploy_status
设置为表中的现有值,而不管您传入的值。同样,您的select count(*)
将计算在内表格中app_ext_code
,zone_env_code
和version_number
为not null
的所有行都是p_
,无论它们是否具有您传入的值。
避免这种情况的最常见方法是对参数和局部变量使用一致的前缀或后缀,以区别于列的名称。例如,我使用l_
作为参数名称的前缀,使用create or replace PROCEDURE sp_Insert_ProfileStatus(
P_APP_EXT_CODE IN PROFILE_STATUS.APP_EXT_CODE%TYPE,
P_ZONE_ENV_CODE IN PROFILE_STATUS.ZONE_ENV_CODE%TYPE,
P_VERSION_NUMBER IN PROFILE_STATUS.VERSION_NUMBER%TYPE,
P_DEPLOY_STATUS IN PROFILE_STATUS.DEPLOY_STATUS%TYPE
)
IS
tmpCnt number;
BEGIN
SELECT COUNT(*)
INTO tmpCnt
FROM WAF1_PROFILE_STATUS
WHERE APP_EXT_CODE = P_APP_EXT_CODE
AND ZONE_ENV_CODE = P_ZONE_ENV_CODE
AND VERSION_NUMBER = P_VERSION_NUMBER;
dbms_output.put_line('count:'||tmpCnt);
IF tmpCnt > 0
THEN
UPDATE WAF1_PROFILE_STATUS
SET DEPLOY_STATUS = P_DEPLOY_STATUS
WHERE APP_EXT_CODE = P_APP_EXT_CODE
AND ZONE_ENV_CODE = P_ZONE_ENV_CODE
AND VERSION_NUMBER = P_VERSION_NUMBER;
ELSE
INSERT INTO WAF1_PROFILE_STATUS(WPS_ID,
APP_EXT_CODE,
ZONE_ENV_CODE,
VERSION_NUMBER,
DEPLOY_STATUS)
VALUES(SYS_GUID(),
P_APP_EXT_CODE,
P_ZONE_ENV_CODE,
P_VERSION_NUMBER,
P_DEPLOY_STATUS);
END IF;
END sp_Insert_ProfileStatus;
作为局部变量的前缀。像
SELECT COUNT(*)
INTO tmpCnt
FROM WAF1_PROFILE_STATUS
WHERE APP_EXT_CODE = sp_Insert_ProfileStatus.APP_EXT_CODE
AND ZONE_ENV_CODE = sp_Insert_ProfileStatus.ZONE_ENV_CODE
AND VERSION_NUMBER = sp_Insert_ProfileStatus.VERSION_NUMBER;
如果您确实希望参数名称与列名相同,您还可以通过在其前面添加过程名称来明确限定所有代码中的参数名称
{{1}}
但是,这种方法会产生对我来说过于冗长的代码。