我有一个基本的SQL查询,我希望将其变成动态游标。
我有一个列列表,我正在检查以查看自上次运行以来值是否已更改,我正在检查的列包括:收入,种族等。
之前和之后的值的输出需要存储在临时表或永久表中以供进一步调查 - 例如价值变化的来源等......
因为列的列表超过600+,我不认为我想编译基本SQL 600次..
是否有更好的方法来编写动态SQL游标来完成此任务? 谢谢!
--- base sql
SELECT a.*,
'Last_name' AS "field_name",
b.LAST_name AS last_name_updated
from
(SELECT person_id, last_name
FROM person
WHERE batch_id = (select max(batch_id) from person)
) a
FULL OUTER JOIN
(SELECT person_id, last_name
FROM person
WHERE batch_id = (select max(batch_id) - 1 from person)
) b
ON a.person_id = b.person_id
WHERE nvl(a.last_name,0) <> nvl(b.last_nm,0)
UNION
SELECT a.*,
'Income',
b.income AS income_updated
from
(SELECT person_id, income
FROM person
WHERE batch_id = (select max(batch_id) from person)
) a
FULL OUTER JOIN
(SELECT person_id, income
FROM person
WHERE batch_id = (select max(batch_id) - 1 from person)
) b
ON a.person_id = b.person_id
WHERE nvl(a.income,0) <> nvl(b.income,0)
---期望的输出
person_id || field_name || previous_value || updated_value
8783 || income || 95000 || 98000
235731 || last_name || Dawson || Dawson Jr.
答案 0 :(得分:0)
这是让你入门的东西。它不是用600个联合生成一个巨大的查询,而是生成600个查询并按顺序运行它们。您需要添加代码以将每次迭代的结果保存到另一个表中:
declare
l_sql long;
l_default varchar2(10);
l_max_batch_id number;
rc sys_refcursor;
begin
select max(batch_id)
into l_max_batch_id
from person;
for r in (select column_name, data_type
from user_tab_columns
where table_name = 'PERSON'
and column_name not in ('PERSON_ID') -- Exclude any other columns you don't want to compare
)
loop
l_sql := q'[SELECT a.person_id,
a.col AS new_value
'#COL#' AS column_name,
b.#COL# AS old_value
from
(SELECT person_id, #COL#
FROM person
WHERE batch_id = #MAXBATCH#
) a
FULL OUTER JOIN
(SELECT person_id, #COL#
FROM person
WHERE batch_id = #MAXBATCH#-1
) b
ON a.person_id = b.person_id
WHERE nvl(a.#COL#,#DEFAULT#) <> nvl(b.#COL#,#DEFAULT#)]';
l_sql := replace (l_sql, '#COL#', r.column_name);
l_sql := replace (l_sql, '#MAXBATCH#', l_max_batch_id);
l_default := case r.data_type
when 'NUMBER' then '0'
when 'DATE' then q'[DATE '4000-31-12']'
else q'['~~~']'
end;
l_sql := replace (l_sql, '#DEFAULT#', l_default);
open rc for l_sql;
-- Now fetch all the data and e.g. write to a table...
end loop;
end;