【发布时间】:2018-08-07 22:17:33
【问题描述】:
我正在做转置,并查看某些列是否存在与其他表完全相同的值。示例:
tableA: id = 10, col = abc , value = 10
tableB: id = 10, abc = 10
我有以下代码:
declare
TYPE t_my_list is record(id VARCHAR2(4000),col VARCHAR2(4000),val VARCHAR2(4000));
Type list_3STR is table of t_my_list;
v_stmt VARCHAR2(32000) := 'SELECT id, col, val FROM userA.tableA';
v_lstmt VARCHAR2(32000);
v_ret list_3STR := list_3STR();
cDel number;
begin
EXECUTE IMMEDIATE v_stmt BULK COLLECT INTO v_ret;
for i in v_ret.first..v_ret.last loop
--DBMS_OUTPUT.PUT_LINE('ID: '||v_ret (i).id||', COL: '||v_ret (i).col||', VAL: '||v_ret (i).val);
v_lstmt := 'SELECT count(*) FROM userB.tableB WHERE NVL(cast('||v_ret (i).col||' as Varchar2(100)), ''<null>'') in ('''||v_ret (i).val||''', ''<null>'') and ID = '''||v_ret (i).id||''' ';
DBMS_OUTPUT.PUT_LINE(v_lstmt);
EXECUTE IMMEDIATE v_lstmt INTO cDel;
If cDel > 0 Then
DBMS_OUTPUT.PUT_LINE('delete row from userA.tableA')
End if;
end loop;
DBMS_OUTPUT.PUT_LINE('v_ret = '||v_ret.count);
end;
我必须考虑5个案例:
userA.tableA 到 userB.tableB
- NULL 到 NULL = 1 --DELETE 值
- NULL 到 DATA = 0 --NOT DELETE
- 相同的 DATA 到 DATA = 1 --DELETE
- 不同的数据到不同的数据 = 0 --NOT DELETE
- DATA 为 NULL = 0 = --NOT DELETE
我的代码适用于案例 1 到 4。如何解决第 5 个问题?
更新:案例示例:
1.
id = 10, col = test, val = null
id = 10, test = null
2.
id = 10, col = test, val = null
id = 10, test = 99
3.
id = 10, col = test, val = 99
id = 10, test = 99
4.
id = 10, col = test, val = 5
id = 10, test = 99
5.
id = 10, col = test, val = 4
id = 10, test = null
【问题讨论】:
-
动态SQL有原因吗?是否有一些限制,阻止写一个删除语句并在“where”部分指定逻辑?
-
另外,请提供与每个场景匹配的示例输入数据,并提供您期望的输出。
-
@4est 您不能使用游标,因为这是您公司的标准?怎么回事?这就像说你只能用鼻子打字来完成你的工作。 *皱眉* 如果是出于性能原因,因为 10g 循环游标已优化为在幕后执行
bulk collect ... limit 100。此外,在不使用限制子句的情况下进行批量收集 - 正如您在示例代码中所做的那样 - 会占用大量内存;我想这应该是你的标准的一部分,不要在没有限制条款的情况下批量收集? -
@4est - 你的意思是删除,而不是删除?通常不应即时创建或删除表。但是如果它们被删除,你会从你的包中得到一个运行时错误;如果它们被删除并重新创建,包将在下次调用时自动重新编译。 (另外,您可以在不使用批量收集的情况下使用带游标的动态 SQL...)
-
同样在your previous question 中,我展示了使用
is null而不是nvl(),这适用于场景2 和5。你为什么回到nvl()和魔法值?
标签: sql oracle plsql null transpose