将 table 名称和时间戳变量传递给 PL/SQL
Pass a table name and time stamp variable to a PL/SQL
我正在 SQL 开发人员中编写下面的 PL/SQL 代码,以从 table 中删除数据,并在 where 条件中包含时间戳列。我如何修改此代码以根据我想要从中删除数据的 table 和时间记录将 table 名称和时间戳值传递给我想要的值并创建一个存储过程重复使用。
DBMS_OUTPUT.ENABLE;
DECLARE
counter INTEGER := 0;
stop INTEGER;
BEGIN
dbms_output.put_line('START');
LOOP
counter := counter + 1;
DELETE my_schema.test
WHERE t = '10-JUN-20 04.33.46.000000000 AM'
AND ROWNUM <= 100000;
SELECT COUNT(*)
INTO stop
FROM my_schema.test
WHERE t = '10-JUN-20 04.33.46.000000000 AM';
EXIT WHEN stop <= 0;
COMMIT;
END LOOP;
dbms_output.put_line('Counter: ' || counter);
dbms_output.put_line('Left: ' || stop);
COMMIT;
END;
我无法对其进行测试,但您可以创建一个将 table 名称和时间戳作为参数的函数。
只要您想删除具有给定时间戳的每条记录,您就不需要为每条记录循环。
这个函数应该只是一个例子。
FUNCTION delete_values_by_timestamp (p_table_name IN VARCHAR2 DEFAULT NULL,
p_timestamp IN VARCHAR2 DEFAULT NULL)
RETURN VARCHAR2
IS
v_count NUMBER := 0;
v_query VARCHAR2 (500) := '';
BEGIN
IF p_table_name IS NOT NULL
THEN
IF p_timestamp IS NOT NULL
THEN
v_query := 'SELECT COUNT(*)
FROM my_schema.' || p_table_name | '
WHERE t = TO_DATE(''' || p_timestamp ||''', ''DD.MM.YYYY HH24:MI:SS.SSSS'')';
EXECUTE IMMEDIATE v_query INTO v_count;
IF v_count > 0
THEN
v_query := 'DELETE FROM my_schema.' || p_table_name || '
WHERE t = TO_DATE(''' || p_timestamp ||''', ''DD.MM.YYYY HH24:MI:SS.SSSS'')';
EXECUTE IMMEDIATE v_query;
ELSE
RETURN 'NO RECORDS FOUND!';
END IF;
ELSE
RETURN 'TIMESTAMP EMPTY!';
END IF;
ELSE
RETURN 'TABLE NAME EMPTY!';
END IF;
END;
如前所述,使匿名存储过程适应存储过程需要将其转换为动态 SQL。总是更难。并受到SQL注射。为此,您应该验证字符串替换参数。我还有一些其他更改:
- 将所需的作为时间戳而不是字符串传递,这 allows/forces
调用例程以确定格式和必要的转换,如果
任何。
- 也为列名添加了一个参数。这释放命名列
从程序的要求。
- 无需清点剩余物品。你的循环过程直到
该值达到 0,但这可以由
最后一次删除的行。删除将 sql%rowcount 设置为数字
删除的行数。当传递删除 0 行时,过程是
完成。
- 再次从过程中删除了结果显示和提交
将其卸载给调用者。
create or replace
procedure delete_values_by_timestamp
( p_table_name in varchar2
, p_column_name in varchar2
, p_timestamp in timestamp
, p_result_msg out varchar2
)
IS
table_name_parameter_invalid exception;
pragma exception_init(table_name_parameter_invalid, -44002);
column_name_parameter_invalid exception;
pragma exception_init(column_name_parameter_invalid, -44003);
k_nl constant varchar2(1) := chr(10);
k_max_delete_per_interation constant integer := 100000;
k_base_delete varchar2(256) :=
'delete from <table_name>' ||
' where <column_name> <= :1' ||
' and rownum <= :2';
v_delete_sql varchar2 (256) ;
v_rows_deleted integer := 0;
begin
v_delete_sql := replace(replace(k_base_delete,'<table_name>', dbms_assert.sql_object_name(p_table_name))
,'<column_name>',dbms_assert.simple_sql_name(p_column_name));
dbms_output.put_line('Running SQL:' || k_nl || v_delete_sql);
loop
execute immediate v_delete_sql using p_timestamp, k_max_delete_per_interation;
exit when sql%rowcount = 0;
v_rows_deleted :=v_rows_deleted + sql%rowcount;
end loop;
if v_rows_deleted = 0
then
p_result_msg := 'No Data Found';
else
p_result_msg := 'Number of Rows Deleted ' || to_char(v_rows_deleted);
end if;
exception
when table_name_parameter_invalid then
raise_application_error(-20199,'Invalid Table Name (' || p_table_name || ') specified.');
when column_name_parameter_invalid then
raise_application_error(-20198,'Invalid Column Name (' || p_column_name || ') specified.');
end delete_values_by_timestamp;
参见example:在示例中,我将每次迭代删除的行数从 100000 减少到 20。另外的增强功能是将每次迭代的行数作为参数传递。
我正在 SQL 开发人员中编写下面的 PL/SQL 代码,以从 table 中删除数据,并在 where 条件中包含时间戳列。我如何修改此代码以根据我想要从中删除数据的 table 和时间记录将 table 名称和时间戳值传递给我想要的值并创建一个存储过程重复使用。
DBMS_OUTPUT.ENABLE;
DECLARE
counter INTEGER := 0;
stop INTEGER;
BEGIN
dbms_output.put_line('START');
LOOP
counter := counter + 1;
DELETE my_schema.test
WHERE t = '10-JUN-20 04.33.46.000000000 AM'
AND ROWNUM <= 100000;
SELECT COUNT(*)
INTO stop
FROM my_schema.test
WHERE t = '10-JUN-20 04.33.46.000000000 AM';
EXIT WHEN stop <= 0;
COMMIT;
END LOOP;
dbms_output.put_line('Counter: ' || counter);
dbms_output.put_line('Left: ' || stop);
COMMIT;
END;
我无法对其进行测试,但您可以创建一个将 table 名称和时间戳作为参数的函数。 只要您想删除具有给定时间戳的每条记录,您就不需要为每条记录循环。 这个函数应该只是一个例子。
FUNCTION delete_values_by_timestamp (p_table_name IN VARCHAR2 DEFAULT NULL,
p_timestamp IN VARCHAR2 DEFAULT NULL)
RETURN VARCHAR2
IS
v_count NUMBER := 0;
v_query VARCHAR2 (500) := '';
BEGIN
IF p_table_name IS NOT NULL
THEN
IF p_timestamp IS NOT NULL
THEN
v_query := 'SELECT COUNT(*)
FROM my_schema.' || p_table_name | '
WHERE t = TO_DATE(''' || p_timestamp ||''', ''DD.MM.YYYY HH24:MI:SS.SSSS'')';
EXECUTE IMMEDIATE v_query INTO v_count;
IF v_count > 0
THEN
v_query := 'DELETE FROM my_schema.' || p_table_name || '
WHERE t = TO_DATE(''' || p_timestamp ||''', ''DD.MM.YYYY HH24:MI:SS.SSSS'')';
EXECUTE IMMEDIATE v_query;
ELSE
RETURN 'NO RECORDS FOUND!';
END IF;
ELSE
RETURN 'TIMESTAMP EMPTY!';
END IF;
ELSE
RETURN 'TABLE NAME EMPTY!';
END IF;
END;
如前所述,使匿名存储过程适应存储过程需要将其转换为动态 SQL。总是更难。并受到SQL注射。为此,您应该验证字符串替换参数。我还有一些其他更改:
- 将所需的作为时间戳而不是字符串传递,这 allows/forces 调用例程以确定格式和必要的转换,如果 任何。
- 也为列名添加了一个参数。这释放命名列 从程序的要求。
- 无需清点剩余物品。你的循环过程直到 该值达到 0,但这可以由 最后一次删除的行。删除将 sql%rowcount 设置为数字 删除的行数。当传递删除 0 行时,过程是 完成。
- 再次从过程中删除了结果显示和提交 将其卸载给调用者。
create or replace
procedure delete_values_by_timestamp
( p_table_name in varchar2
, p_column_name in varchar2
, p_timestamp in timestamp
, p_result_msg out varchar2
)
IS
table_name_parameter_invalid exception;
pragma exception_init(table_name_parameter_invalid, -44002);
column_name_parameter_invalid exception;
pragma exception_init(column_name_parameter_invalid, -44003);
k_nl constant varchar2(1) := chr(10);
k_max_delete_per_interation constant integer := 100000;
k_base_delete varchar2(256) :=
'delete from <table_name>' ||
' where <column_name> <= :1' ||
' and rownum <= :2';
v_delete_sql varchar2 (256) ;
v_rows_deleted integer := 0;
begin
v_delete_sql := replace(replace(k_base_delete,'<table_name>', dbms_assert.sql_object_name(p_table_name))
,'<column_name>',dbms_assert.simple_sql_name(p_column_name));
dbms_output.put_line('Running SQL:' || k_nl || v_delete_sql);
loop
execute immediate v_delete_sql using p_timestamp, k_max_delete_per_interation;
exit when sql%rowcount = 0;
v_rows_deleted :=v_rows_deleted + sql%rowcount;
end loop;
if v_rows_deleted = 0
then
p_result_msg := 'No Data Found';
else
p_result_msg := 'Number of Rows Deleted ' || to_char(v_rows_deleted);
end if;
exception
when table_name_parameter_invalid then
raise_application_error(-20199,'Invalid Table Name (' || p_table_name || ') specified.');
when column_name_parameter_invalid then
raise_application_error(-20198,'Invalid Column Name (' || p_column_name || ') specified.');
end delete_values_by_timestamp;
参见example:在示例中,我将每次迭代删除的行数从 100000 减少到 20。另外的增强功能是将每次迭代的行数作为参数传递。