首页 > 数据库 > 国内数据库 > 羲和(Halo)数据库——DBMS_SQL浅尝
本文将向大家展示如何在羲和(Halo)数据库中使用DBMS_SQL,本文测试案例除部分表结构和部分测试数据之外,其余均来自ORACLE官方测试文档,所有测试案例放置文章末尾以供学习使用。
DBMS_SQL是 ORACLE数据库提供的一个系统包,用于执行动态SQL,支持使用DDL和DML等。DBMS_SQL整体运行流程图如下:
下面简单介绍一下本文中所使用到的DBMS_SQL部分接口,如果查看更为详细的介绍,建议参考ORACLE官方文档。
c := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(c, 'INSERT INTO tab VALUES (:bnd1, :bnd2) ' || 'RETURNING c1*c2 INTO :bnd3', DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(c, 'bnd1', c1);
DBMS_SQL.BIND_ARRAY(c, 'bnd3', r);
DBMS_SQL.DEFINE_COLUMN(source_cursor, 1, id_var);
n := DBMS_SQL.EXECUTE(c);
IF DBMS_SQL.FETCH_ROWS(source_cursor)>0 THEN -- get column values of the row
r := DBMS_SQL.EXECUTE_AND_FETCH(c);
DBMS_SQL.VARIABLE_VALUE(c, 'bnd3', r);
DBMS_SQL.COLUMN_VALUE(c, 1, some_dnames);
DBMS_SQL.CLOSE_CURSOR(c);
接下来我将使用羲和(Halo)数据库演示上述DBMS_SQL的各个接口。
羲和(Halo)数据库设置为ORACLE模式,创建一个演示数据库test_db,创建内部所需的ORACLE拓展。
当需要使用oracle相关的特性,建议直接使用hsql进行登录使用。所以此处使用hsql -dtest_db,登录test_db数据库进行接下来的相关操作。
multi_Row_update:将c2为11,对应的c1更新成100
exec:支持运行DDL和没有绑定参数的DML语句。
copy:将源表中的数据复制到目标表,这个存储过程有助于帮助大家理解和使用DBMS_SQL。
-- 单行插入
CREATE TABLE tab(c1 NUMBER, c2 NUMBER); -- 依据ORACLE测试案例 创建tab表
CREATE OR REPLACE PROCEDURE single_Row_insert
(c1 NUMBER, c2 NUMBER, r OUT NUMBER) is
c NUMBER;
n NUMBER;
begin
c := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(c, 'INSERT INTO tab VALUES (:bnd1, :bnd2) ' ||
'RETURNING c1*c2 INTO :bnd3', DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(c, 'bnd1', c1);
DBMS_SQL.BIND_VARIABLE(c, 'bnd2', c2);
DBMS_SQL.BIND_VARIABLE(c, 'bnd3', r);
n := DBMS_SQL.EXECUTE(c);
DBMS_SQL.VARIABLE_VALUE(c, 'bnd3', r); -- get value of outbind variable
DBMS_SQL.CLOSE_CURSOR(c);
END;
/
declare
c3 number(7,2);
begin
single_Row_insert(5, 10, c3);
dbms_output.put_line('c3 = '|| c3);
end;
/
select * from tab;
-- 单行更新
CREATE OR REPLACE PROCEDURE single_Row_update
(c1 NUMBER, c2 NUMBER, r out NUMBER) IS
c NUMBER;
n NUMBER;
BEGIN
c := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(c, 'UPDATE tab SET c1 = :bnd1, c2 = :bnd2 ' ||
'WHERE rownum < 2' ||
'RETURNING c1*c2 INTO :bnd3', DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(c, 'bnd1', c1);
DBMS_SQL.BIND_VARIABLE(c, 'bnd2', c2);
DBMS_SQL.BIND_VARIABLE(c, 'bnd3', r);
n := DBMS_SQL.EXECUTE(c);
DBMS_SQL.VARIABLE_VALUE(c, 'bnd3', r);-- get value of outbind variable
DBMS_SQL.CLOSE_CURSOR(c);
END;
/
-- 调用single_Row_update
declare
c3 number(7,2);
begin
single_Row_update(5, 5, c3);
dbms_output.put_line('c3 = '|| c3);
end;
/
-- 查看数据是否更新成功
select * from tab;
-- 单行删除
CREATE OR REPLACE PROCEDURE single_Row_Delete
(c1 NUMBER, r OUT NUMBER) is
c NUMBER;
n number;
BEGIN
c := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(c, 'DELETE FROM tab WHERE ROWNUM = :bnd1 ' ||
'RETURNING c1*c2 INTO :bnd2', DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(c, 'bnd1', c1);
DBMS_SQL.BIND_VARIABLE(c, 'bnd2', r);
n := DBMS_SQL.EXECUTE(c);
DBMS_SQL.VARIABLE_VALUE(c, 'bnd2', r);-- get value of outbind variable
DBMS_SQL.CLOSE_CURSOR(c);
END;
/
-- 调用single_Row_Delete
declare
c3 number(7,2);
begin
single_Row_Delete(1, c3); -- ROWNUM = 1 删除一行数据
dbms_output.put_line('c3 = '|| c3);
end;
/
-- 查看删除结果
select * from tab;
-- 插入多行
CREATE OR REPLACE PROCEDURE multi_Row_insert
(c1 DBMS_SQL.NUMBER_TABLE, c2 DBMS_SQL.NUMBER_TABLE,
r OUT DBMS_SQL.NUMBER_TABLE) is
c NUMBER;
n NUMBER;
BEGIN
c := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(c, 'insert into tab VALUES (:bnd1, :bnd2) ' ||
'RETURNING c1*c2 INTO :bnd3', DBMS_SQL.NATIVE);
DBMS_SQL.BIND_ARRAY(c, 'bnd1', c1);
DBMS_SQL.BIND_ARRAY(c, 'bnd2', c2);
DBMS_SQL.BIND_ARRAY(c, 'bnd3', r);
n := DBMS_SQL.EXECUTE(c);
DBMS_SQL.VARIABLE_VALUE(c, 'bnd3', r);-- get value of outbind variable
DBMS_SQL.CLOSE_CURSOR(c);
END;
/
-- 调用multi_Row_insert
DECLARE
my_number_table DBMS_SQL.NUMBER_TABLE;
my_number_table2 DBMS_SQL.NUMBER_TABLE;
my_number_table3 DBMS_SQL.NUMBER_TABLE;
BEGIN
my_number_table(1) := 10;
my_number_table(2) := 20;
my_number_table(3) := 30;
my_number_table2(1) := 11;
my_number_table2(2) := 21;
my_number_table2(3) := 31;
multi_Row_insert(my_number_table,my_number_table2,my_number_table3);
-- 查看my_number_table3数据
for i in 1 .. my_number_table3.count loop
dbms_output.put_line('c1*c2 = ' || my_number_table3(i));
end loop;
END;
/
-- 查看数据是否插入成功
select * from tab;
-- 再次调用multi_Row_insert 为multi_Row_update做准备
DECLARE
my_number_table DBMS_SQL.NUMBER_TABLE;
my_number_table2 DBMS_SQL.NUMBER_TABLE;
my_number_table3 DBMS_SQL.NUMBER_TABLE;
BEGIN
my_number_table(1) := 10;
my_number_table(2) := 20;
my_number_table(3) := 30;
my_number_table2(1) := 11;
my_number_table2(2) := 21;
my_number_table2(3) := 31;
multi_Row_insert(my_number_table,my_number_table2,my_number_table3);
-- 查看my_number_table3数据
for i in 1 .. my_number_table3.count loop
dbms_output.put_line('c1*c2 = ' || my_number_table3(i));
end loop;
END;
/
-- 查看数据
select * from tab;
-- 多行更新
CREATE OR REPLACE PROCEDURE multi_Row_update
(c1 NUMBER, c2 NUMBER, r OUT DBMS_SQL.NUMBER_TABLE) IS
c NUMBER;
n NUMBER;
BEGIN
c := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(c, 'UPDATE tab SET c1 = :bnd1 WHERE c2 = :bnd2 ' ||
'RETURNING c1*c2 INTO :bnd3', DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(c, 'bnd1', c1);
DBMS_SQL.BIND_VARIABLE(c, 'bnd2', c2);
DBMS_SQL.BIND_ARRAY(c, 'bnd3', r);
n := DBMS_SQL.EXECUTE(c);
DBMS_SQL.VARIABLE_VALUE(c, 'bnd3', r);-- get value of outbind variable
DBMS_SQL.CLOSE_CURSOR(c);
END;
/
-- 调用multi_Row_update
DECLARE
my_number_table3 DBMS_SQL.NUMBER_TABLE;
BEGIN
multi_Row_update(100, 11, my_number_table3);
for i in 1 .. my_number_table3.count loop
dbms_output.put_line(' cur value := ' || my_number_table3(i));
end loop;
END;
/
-- 查看是否更新成功
select * from tab;
-- 多行删除
CREATE OR REPLACE PROCEDURE multi_row_delete
(c1 DBMS_SQL.NUMBER_TABLE,
r OUT DBMS_SQL.NUMBER_TABLE) is
c NUMBER;
n NUMBER;
BEGIN
c := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(c, 'DELETE FROM tab WHERE c1 = :bnd1 ' ||
'RETURNING c1*c2 INTO :bnd2', DBMS_SQL.NATIVE);
DBMS_SQL.BIND_ARRAY(c, 'bnd1', c1);
DBMS_SQL.BIND_ARRAY(c, 'bnd2', r);
n := DBMS_SQL.EXECUTE(c);
DBMS_SQL.VARIABLE_VALUE(c, 'bnd2', r);-- get value of outbind variable
DBMS_SQL.CLOSE_CURSOR(c);
END;
/
-- 调用multi_Row_delete
DECLARE
my_number_table DBMS_SQL.NUMBER_TABLE;
my_number_table3 DBMS_SQL.NUMBER_TABLE;
BEGIN
my_number_table(1) := 100;
my_number_table(2) := 20;
my_number_table(3) := 30;
multi_Row_delete(my_number_table, my_number_table3);
for i in 1 .. my_number_table3.count loop
dbms_output.put_line('c1*c2 = ' || my_number_table3(i));
end loop;
END;
/
-- 查看是否删除成功
select * from tab;
-- exec
CREATE OR REPLACE PROCEDURE exec(STRING IN varchar2) AS
cursor_name NUMBER;
ret INTEGER;
BEGIN
cursor_name := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(cursor_name, string, DBMS_SQL.NATIVE);
ret := DBMS_SQL.EXECUTE(cursor_name);
DBMS_SQL.CLOSE_CURSOR(cursor_name);
END;
/
call exec('create table acct(id NUMBER, name VARCHAR2(30), birthdate DATE)');
-- 2024年了...
insert into acct values(1, 'acct1', TO_DATE('2024-01-01', 'YYYY-MM-DD'));
insert into acct values(2, 'acct2', TO_DATE('2024-01-02', 'YYYY-MM-DD'));
insert into acct values(3, 'acct3', TO_DATE('2024-01-03', 'YYYY-MM-DD'));
insert into acct values(4, 'acct4', TO_DATE('2024-01-04', 'YYYY-MM-DD'));
-- 设置date输出显示格式
alter session set nls_date_format='DD-MON-YY';
select * from acct;
-- copy
-- 准备目标表
create table acct_test(id NUMBER, name VARCHAR2(30), birthdate DATE);
CREATE OR REPLACE PROCEDURE copy (
source IN VARCHAR2,
destination IN VARCHAR2) IS
id_var NUMBER;
name_var VARCHAR2(30);
birthdate_var DATE;
source_cursor INTEGER;
destination_cursor INTEGER;
ignore INTEGER;
BEGIN
-- Prepare a cursor to select from the source table:
source_cursor := dbms_sql.open_cursor;
DBMS_SQL.PARSE(source_cursor,
'SELECT id, name, birthdate FROM ' || source,
DBMS_SQL.NATIVE);
DBMS_SQL.DEFINE_COLUMN(source_cursor, 1, id_var);
DBMS_SQL.DEFINE_COLUMN(source_cursor, 2, name_var, 30);
DBMS_SQL.DEFINE_COLUMN(source_cursor, 3, birthdate_var);
ignore := DBMS_SQL.EXECUTE(source_cursor);
-- Prepare a cursor to insert into the destination table:
destination_cursor := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(destination_cursor,
'INSERT INTO ' || destination ||
' VALUES (:id_bind, :name_bind, :birthdate_bind)',
DBMS_SQL.NATIVE);
-- Fetch a row from the source table and insert it into the destination table:
LOOP
IF DBMS_SQL.FETCH_ROWS(source_cursor)>0 THEN
-- get column values of the row
DBMS_SQL.COLUMN_VALUE(source_cursor, 1, id_var);
DBMS_SQL.COLUMN_VALUE(source_cursor, 2, name_var);
DBMS_SQL.COLUMN_VALUE(source_cursor, 3, birthdate_var);
-- Bind the row into the cursor that inserts into the destination table. You
-- could alter this example to require the use of dynamic SQL by inserting an
-- if condition before the bind.
DBMS_SQL.BIND_VARIABLE(destination_cursor, ':id_bind', id_var);
DBMS_SQL.BIND_VARIABLE(destination_cursor, ':name_bind', name_var);
DBMS_SQL.BIND_VARIABLE(destination_cursor, ':birthdate_bind',
birthdate_var);
ignore := DBMS_SQL.EXECUTE(destination_cursor);
ELSE
-- No more rows to copy:
EXIT;
END IF;
END LOOP;
-- Commit and close all cursors:
COMMIT;
DBMS_SQL.CLOSE_CURSOR(source_cursor);
DBMS_SQL.CLOSE_CURSOR(destination_cursor);
EXCEPTION
WHEN OTHERS THEN
IF DBMS_SQL.IS_OPEN(source_cursor) THEN
DBMS_SQL.CLOSE_CURSOR(source_cursor);
END IF;
IF DBMS_SQL.IS_OPEN(destination_cursor) THEN
DBMS_SQL.CLOSE_CURSOR(destination_cursor);
END IF;
RAISE;
END;
/
-- 运行copy
exec copy('acct','acct_test');
select * from acct_test;
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70036312/viewspace-3009826/ ,如需转载,请注明出处,否则将追究法律责任。