Sql 如何在oracle存储过程中创建和执行动态查询?
我需要在存储过程中动态创建和执行查询 我有两个表用户和用户更新 员工表有Sql 如何在oracle存储过程中创建和执行动态查询?,sql,oracle,stored-procedures,Sql,Oracle,Stored Procedures,我需要在存储过程中动态创建和执行查询 我有两个表用户和用户更新 员工表有emp\u id、用户名、部门、产品、地区、职务等。 员工更新包括emp\u id、生效日期、列名称、新值等列。 基本上这就是我想做的 获取在给定生效日期的用户自定义表中有更新的所有员工 对每个员工进行循环 获取给定生效日期内每个员工的所有更新。在employee_updates表中,员工可能有一个或多个更新 基于这些更新创建动态“更新”查询,如 更新员工集合col1=new\u val\u 1,col2=new\u
emp\u id、用户名、部门、产品、地区、职务等。
员工更新包括emp\u id、生效日期、列名称、新值等列。
基本上这就是我想做的
更新员工集合col1=new\u val\u 1,col2=new\u val\u 2,其中emp\u id=?
create or replace
PROCEDURE SP_RUN_EMPLOYEE_UPDATES
(
IN_DATE IN DATE
)
IS
update_sql varchar2(225);
employee_id BI_EMPLOYEE_UPDATE.employee_id%TYPE;
CURSOR employees
IS SELECT distinct(employee_id)
FROM BI_EMPLOYEE_UPDATE
WHERE EFFECTIVE_DATE = to_date(IN_DATE,'dd-mm-yy')
AND EXECUTED = 'N' AND ACTIVITY_ID = '0'
;
CURSOR e_updates
IS SELECT *
FROM BI_EMPLOYEE_UPDATE
WHERE EFFECTIVE_DATE = to_date(IN_DATE,'dd-mm-yy')
AND EXECUTED = 'N'
AND ACTIVITY_ID = '0'
and employee_id = employee_id ;
BEGIN
OPEN employees;
LOOP
FETCH employees into employee_id;
EXIT WHEN employees%NOTFOUND;
FOR e_update in e_updates
update_sql := 'UPDATE BI_EMPLOYEE SET ';
LOOP
-- create dynam,ic update statment
UPDATE BI_EMPLOYEE_UPDATE
SET EXECUTED = 'Y'
WHERE EMPLOYEE_UPDATE_ID = e_update.EMPLOYEE_UPDATE_ID ;
END LOOP;
-- run dynamic sql
END LOOP;
CLOSE employees;
END;
请提供帮助。您在这里遇到了一些问题,包括:
被声明为日期,因此您无需将其通过IN\u DATE
传递到\u DATE()
- 您只需要一个游标循环;如果出于某种原因希望同时处理
的所有更新,则可以添加员工id
子句order by
- 您根本不需要动态SQL;可以将光标中的值用作静态SQL更新的一部分
CREATE OR REPLACE PROCEDURE sp_run_employee_updates (p_date IN DATE) IS
CURSOR c_updates IS
SELECT *
FROM bi_employee_update
WHERE effective_date = p_date
AND executed = 'N'
AND activity_id = '0'
FOR UPDATE;
BEGIN
-- loop around all pending records
FOR r_update IN c_updates LOOP
-- apply this update to the bi_employee record
UPDATE bi_employee
SET col1 = r_update.col1, col2 = r_update.col2
WHERE emp_id = r_update.employee_id;
-- mark this update as executed
UPDATE bi_employee_update
SET executed = 'Y'
WHERE CURRENT OF c_updates;
END LOOP;
END sp_run_employee_updates;
这是使用for update
和where current of
构造来锁定正在使用的行并简化更新;请参阅文档
值得注意的是,如果
effective_date
或p_date
中有一个时间分量,它们将不匹配。p\u date
不太可能,但是effective\u date
更难猜测。如果确实如此,则您需要trunc()
it,或者使用between
查找时间范围。这里有一些问题,包括:
被声明为日期,因此您无需将其通过IN\u DATE
传递到\u DATE()
- 您只需要一个游标循环;如果出于某种原因希望同时处理
的所有更新,则可以添加员工id
子句order by
- 您根本不需要动态SQL;可以将光标中的值用作静态SQL更新的一部分
CREATE OR REPLACE PROCEDURE sp_run_employee_updates (p_date IN DATE) IS
CURSOR c_updates IS
SELECT *
FROM bi_employee_update
WHERE effective_date = p_date
AND executed = 'N'
AND activity_id = '0'
FOR UPDATE;
BEGIN
-- loop around all pending records
FOR r_update IN c_updates LOOP
-- apply this update to the bi_employee record
UPDATE bi_employee
SET col1 = r_update.col1, col2 = r_update.col2
WHERE emp_id = r_update.employee_id;
-- mark this update as executed
UPDATE bi_employee_update
SET executed = 'Y'
WHERE CURRENT OF c_updates;
END LOOP;
END sp_run_employee_updates;
这是使用for update
和where current of
构造来锁定正在使用的行并简化更新;请参阅文档
值得注意的是,如果effective_date
或p_date
中有一个时间分量,它们将不匹配。p\u date
不太可能,但是effective\u date
更难猜测。如果是这样,那么您需要trunc()
it,或者使用between
查找时间范围。适用于在运行时之前不知道SQL将是什么样子的情况。这里的情况似乎不是这样,所以我认为这个词有误导性。直到运行时才知道这些值,但这很正常。你有什么具体问题?我看到的第一个问题是,变量的名称与列的名称相同,这充其量是令人困惑的,并且可能会产生意外的结果。但无论如何,这种方法似乎很奇怪;您将多次更新每个员工
?为什么是两个循环?用于在运行时之前不知道SQL将是什么样子的情况。这里的情况似乎不是这样,所以我认为这个词有误导性。直到运行时才知道这些值,但这很正常。你有什么具体问题?我看到的第一个问题是,变量的名称与列的名称相同,这充其量是令人困惑的,并且可能会产生意外的结果。但无论如何,这种方法似乎很奇怪;您将多次更新每个员工
?为什么是两个循环?