• 动态SQL


     

    范例:利用动态SQL在执行时创建一张数据表

    CREATE OR REPLACE FUNCTION get_table_count_fun(p_table_name VARCHAR2) RETURN NUMBER AS

    v_sql_statement VARCHAR2(200) ; -- 定义操作的SQL语句

    v_count NUMBER ; -- 保存表中记录

    BEGIN

    SELECT COUNT(*) INTO v_count FROM user_tables WHERE table_name=UPPER(p_table_name) ;

    IF v_count = 0 THEN -- 数据表不存在

    v_sql_statement := 'CREATE TABLE ' || p_table_name ||

    ' ( id NUMBER ,

    name VARCHAR2(30) NOT NULL ,

    CONSTRAINT pk_id_' || p_table_name || ' PRIMARY KEY(id)) ' ; -- 创建数据表

    EXECUTE IMMEDIATE v_sql_statement ; -- 执行动态SQL

    END IF ;

    v_sql_statement := 'SELECT COUNT(*) FROM ' || p_table_name ; -- 查询数据表记录

    EXECUTE IMMEDIATE v_sql_statement INTO v_count ; -- 执行动态SQL并保存数据记录

    RETURN v_count ;

    END ;

    /

    范例:直接在程序中编写DDLDML

    CREATE OR REPLACE FUNCTION get_table_count_fun(p_table_name VARCHAR2) RETURN NUMBER AS

    v_sql_statement VARCHAR2(200) ; -- 定义操作的SQL语句

    v_count NUMBER ; -- 保存表中记录

    BEGIN

    SELECT COUNT(*) INTO v_count FROM user_tables WHERE table_name=UPPER(p_table_name) ;

    IF v_count = 0 THEN -- 数据表不存在

    -- 错误:无法直接使用DDL操作

    CREATE TABLE p_table_name (

    idNUMBER,

    nameVARCHAR2(30)NOT NULL ,

    CONSTRAINT id_pk PRIMARY KEY(id)) ;

    END IF ;

    -- 错误:查询数据表不存在

    SELECT COUNT(*) INTO v_count FROM p_table_name ;

    RETURN v_count ;

    END ;

    /

    范例:编写PL/SQL块调用函数

    BEGIN

    DBMS_OUTPUT.put_line('数据表记录:' || get_table_count_fun('mldnjava')) ;

    END ;

    /

     

    范例:c##scott用户授权

    CONN sys/change_on_install AS SYSDBA ;

    GRANT CREATE ANY TABLE TO c##scott ;

    CONN c##scott/tiger ;

    范例:使用动态SQL创建表和PL/SQL

    DECLARE

    v_sql_statement VARCHAR2(200) ;

    v_count NUMBER ; -- 保存查找结果

    BEGIN

    SELECT COUNT(*) INTO v_count FROM user_tables WHERE table_name='MLDN_TAB' ;

    IF v_count = 0 THEN -- 数据表不存在

    v_sql_statement := 'CREATE TABLE mldn_tab(

    id NUMBER PRIMARY KEY ,

    url VARCHAR2(50) NOT NULL)' ; -- 定义动态SQL

    EXECUTE IMMEDIATE v_sql_statement ;

    ELSE -- 数据表存在

    v_sql_statement := 'TRUNCATE TABLE mldn_tab' ;

    EXECUTE IMMEDIATE v_sql_statement ;

    END IF ;

    v_sql_statement := 'BEGIN

    FOR x IN 1 .. 10 LOOP

    INSERT INTO mldn_tab(id,url) VALUES (x , ''www.mldnjava.cn - '' || x) ;

    END LOOP ;

    END ;' ;

    EXECUTE IMMEDIATE v_sql_statement ;

    COMMIT ; -- 提交事务

    END  ;

    /

    范例:查询mldn_tab数据表

    SELECT * FROM mldn_tab ;

     

    范例:使用绑定变量

    DECLARE

    v_sql_statement VARCHAR2(200) ;

    v_deptno dept.deptno%TYPE := 60 ;

    v_dname dept.dname%TYPE := 'MLDN' ;

    v_loc dept.loc%TYPE := '北京' ;

    BEGIN

    v_sql_statement := 'INSERT INTO dept(deptno,dname,loc) VALUES (:dno , :dna , :dl)' ;

    EXECUTE IMMEDIATE v_sql_statement USING v_deptno,v_dname,v_loc ;

    COMMIT ;

    END  ;

    /

    范例:利用集合更新多条记录

    DECLARE

    v_sql_statement VARCHAR2(200) ;

    TYPE deptno_nested IS TABLE OF dept.deptno%TYPE NOT NULL ;

    TYPE dname_nested IS TABLE OF dept.dname%TYPE NOT NULL ;

    v_deptno deptno_nested := deptno_nested(10,20,30,40) ;

    v_dname dname_nested := dname_nested('财务部','研发部','销售部','操作部') ;

    BEGIN

    v_sql_statement := 'UPDATE dept SET dname=:dna WHERE deptno=:dno' ;

    FOR x IN 1 .. v_deptno.COUNT LOOP

    EXECUTE IMMEDIATE v_sql_statement USING v_dname(x),v_deptno(x) ;

    END LOOP ;

    COMMIT ;

    END  ;

    /

    范例:更新完成后查询dept表记录

    SELECT * FROM dept ;

     

    范例:查询数据

    DECLARE

    v_sql_statement VARCHAR2(200) ;

    v_empno emp.empno%TYPE := 7369 ;

    v_emprow emp%ROWTYPE ;

    BEGIN

    v_sql_statement := 'SELECT * FROM emp WHERE empno=:eno' ;

    EXECUTE IMMEDIATE v_sql_statement INTO v_emprow USING v_empno ;

    DBMS_OUTPUT.put_line('雇员编号:' || v_emprow.empno || ',姓名:' || v_emprow.ename || ',职位:' || v_emprow.job) ;

    END  ;

    /

     

    范例:在创建表时使用绑定变量

    DECLARE

    v_sql_statement VARCHAR2(200) ;

    v_table_name VARCHAR2(200) := 'mldn' ;

    v_id_column VARCHAR2(200) := 'id' ;

    BEGIN

    v_sql_statement := 'CREATE TABLE :tn (:ci NUMBER PRIMARY KEY)' ;

    EXECUTE IMMEDIATE v_sql_statement USING v_table_name,v_id_column ;

    END  ;

    /

     

    范例:正确的代码

    DECLARE

    v_sql_statement VARCHAR2(200) ;

    v_table_name VARCHAR2(200) := 'mldn' ;

    v_id_column VARCHAR2(200) := 'id' ;

    BEGIN

    v_sql_statement := 'CREATE TABLE ' || v_table_name ||' (' || v_id_column ||' NUMBER PRIMARY KEY)' ;

    EXECUTE IMMEDIATE v_sql_statement ;

    END  ;

    /

    范例:更新数据,取得更新后的结果

    DECLARE

    v_sql_statement VARCHAR2(200) ; -- 定义SQL操作语句

    v_empno emp.empno%TYPE := 7369 ; -- 要更新的雇员编号

    v_salary emp.sal%TYPE ; -- 保存更新后的sal内容

    v_job emp.job%TYPE ; -- 保存更新后的job内容

    BEGIN

    v_sql_statement := 'UPDATE emp SET sal=sal*1.2,job=''开发'' ' ||

    ' WHERE empno=:eno RETURNING sal,job INTO :salary,:job' ;

    EXECUTE IMMEDIATE v_sql_statement USING v_empno RETURNING INTO v_salary,v_job ;

    DBMS_OUTPUT.put_line('调整后的工资:' || v_salary || ',新的职位:' || v_job) ;

    END  ;

    /

    范例:删除数据,取得删除前的结果

    DECLARE

    v_sql_statement VARCHAR2(200) ; -- 定义SQL操作语句

    v_emprow emp%ROWTYPE ; -- 保存emp类型

    v_empno emp.empno%TYPE := 7369 ; -- 删除的雇员编号

    v_ename emp.ename%TYPE ; -- 删除的雇员姓名

    v_sal emp.sal%TYPE ; -- 删除的雇员工资

    BEGIN

    v_sql_statement := 'DELETE FROM emp WHERE empno=:eno RETURNING ename,sal INTO :name,:sal' ;

    EXECUTE IMMEDIATE v_sql_statement USING v_empno RETURNING INTO v_ename,v_sal ;

    DBMS_OUTPUT.put_line('删除的雇员编号:' || v_empno || ',姓名:' || v_ename || ',工资:' || v_sal) ;

    END ;

    /

    范例:编写部门增加过程

    CREATE OR REPLACE PROCEDURE dept_insert_proc(

    p_deptno IN OUT dept.deptno%TYPE , -- 此处可以将p_deptno的内容回传

    p_dname dept.dname%TYPE, -- 默认为IN模式

    p_loc dept.loc%TYPE) AS -- 默认为IN模式

    BEGIN

    SELECT MAX(deptno) INTO p_deptno FROM dept ; -- 取得最大的deptno内容

    p_deptno := p_deptno + 1 ; -- 让最大值部门编号加1,此处不考虑超过2位数字情况

    INSERT INTO dept(deptno,dname,loc) VALUES (p_deptno,p_dname,p_loc) ;

    END ;

    /

    范例:编写PL/SQL块,调用过程

    DECLARE

    v_sql_statement VARCHAR2(200) ;

    v_deptno dept.deptno%TYPE ;

    v_dname dept.dname%TYPE := 'MLDN教学部' ;

    v_loc dept.loc%TYPE := '北京' ;

    BEGIN

    v_sql_statement := 'BEGIN

    dept_insert_proc(:dno , :dna , :dl) ;

    END ;' ; -- 定义PL/SQL

    EXECUTE IMMEDIATE v_sql_statement USING IN OUT v_deptno , IN v_dname , v_loc ;

    DBMS_OUTPUT.put_line('新增部门编号为:' || v_deptno) ;

    END ;

    /

    范例:更新时使用BULK COLLECT语句

    DECLARE

    TYPE ename_index IS TABLE OF emp.ename%TYPE INDEX BY PLS_INTEGER ;

    TYPE job_index IS TABLE OF emp.job%TYPE INDEX BY PLS_INTEGER ;

    TYPE sal_index IS TABLE OF emp.sal%TYPE INDEX BY PLS_INTEGER ;

    v_ename ename_index ;

    v_job job_index ;

    v_sal sal_index ;

    v_sql_statement VARCHAR2(200) ; -- 定义动态SQL

    v_deptno emp.deptno%TYPE := 10 ; -- 查询10部门

    BEGIN

    v_sql_statement := 'UPDATE emp SET sal=sal*1.2 WHERE deptno=:dno ' ||

    ' RETURNING ename,job,sal INTO :ena, :ej, :es' ; -- 此时返回多行更新结果

    EXECUTE IMMEDIATE v_sql_statement USING v_deptno

    RETURNING BULK COLLECT INTO v_ename,v_job,v_sal ;

    FOR x IN 1 .. v_ename.COUNT LOOP

    DBMS_OUTPUT.put_line('雇员姓名:' || v_ename(x) || ',职位:' || v_job(x) || ',工资:' || v_sal(x)) ;

    END LOOP ;

    END ;

    /

    范例:查询时使用BULK COLLECT

    DECLARE

    TYPE ename_index IS TABLE OF emp.ename%TYPE INDEX BY PLS_INTEGER ; -- 保存雇员姓名

    TYPE job_index IS TABLE OF emp.job%TYPE INDEX BY PLS_INTEGER ; -- 保存雇员职位

    TYPE sal_index IS TABLE OF emp.sal%TYPE INDEX BY PLS_INTEGER ; -- 保存雇员工资

    v_ename ename_index ;

    v_job job_index ;

    v_sal sal_index ;

    v_sql_statement VARCHAR2(200) ; -- 定义动态SQL

    v_deptno emp.deptno%TYPE := 10 ; -- 查询10部门

    BEGIN

    v_sql_statement := 'SELECT ename,job,sal FROM emp WHERE deptno=:dno' ; -- 此时返回多行更新结果

    EXECUTE IMMEDIATE v_sql_statement

    BULK COLLECT INTO v_ename,v_job,v_sal

    USING v_deptno ; -- 将多个结果一起返回

    FOR x IN 1 .. v_ename.COUNT LOOP

    DBMS_OUTPUT.put_line('雇员姓名:' || v_ename(x) || ',职位:' || v_job(x) || ',工资:' || v_sal(x)) ;

    END LOOP ;

    END ;

    /

    范例:通过FORALL设置多个参数

    DECLARE

    TYPE empno_nested IS TABLE OF emp.empno%TYPE  ; -- 定义嵌套表

    TYPE ename_index IS TABLE OF emp.ename%TYPE INDEX BY PLS_INTEGER ; -- 定义索引表

    TYPE job_index IS TABLE OF emp.job%TYPE INDEX BY PLS_INTEGER ; -- 定义索引表

    TYPE sal_index IS TABLE OF emp.sal%TYPE INDEX BY PLS_INTEGER ; -- 定义索引表

    v_ename ename_index ; -- 保存删除后的姓名

    v_job job_index ; -- 保存删除后的职位

    v_sal sal_index ; -- 保存删除后的工资

    v_empno empno_nested := empno_nested(7369,7566,7788) ; -- 定义要删除雇员编号

    v_sql_statement VARCHAR2(200) ; -- 动态SQL

    BEGIN

    v_sql_statement := 'DELETE FROM emp WHERE empno=:eno ' || '

    RETURNING ename,job,sal INTO :ena , :ej , :es' ; -- 删除数据SQL

    FORALL x IN 1 .. v_empno.COUNT -- FORALL绑定多个变量

    EXECUTE IMMEDIATE v_sql_statement USING v_empno(x)

    RETURNING BULK COLLECT INTO v_ename,v_job,v_sal ;

    FOR x IN 1 .. v_ename.COUNT LOOP

    DBMS_OUTPUT.put_line('雇员姓名:' || v_ename(x) || ',职位:' || v_job(x) || ',工资:' || v_sal(x)) ;

    END LOOP ;

    END ;

    /

     

    范例:在游标中使用动态SQL

    DECLARE

    cur_emp SYS_REFCURSOR ; -- 定义游标变量

    v_emprow emp%ROWTYPE ; -- 定义emp行类型

    v_deptno emp.deptno%TYPE := 10 ; -- 定义要查询雇员的部门编号

    BEGIN

    OPEN cur_emp FOR 'SELECT * FROM emp WHERE deptno=:dno '

    USING v_deptno ;

    LOOP

    FETCH cur_emp INTO v_emprow ; -- 取得游标数据

    EXIT WHEN cur_emp%NOTFOUND ; -- 如果没有数据则退出

    DBMS_OUTPUT.put_line('雇员姓名:' || v_emprow.ename || ',雇员职位:' || v_emprow.job) ;

    END LOOP ;

    CLOSE cur_emp ;

    END ;

    /

    范例:利用FETCH保存查询结果

    DECLARE

    cur_emp SYS_REFCURSOR ; -- 定义游标变量

    TYPE emp_index IS TABLE OF emp%ROWTYPE INDEX BY PLS_INTEGER ; -- 定义索引表

    v_emprow emp_index ; -- 定义emp行类型

    v_deptno emp.deptno%TYPE := 10 ; -- 定义要查询雇员的部门编号

    BEGIN

    OPEN cur_emp FOR 'SELECT * FROM emp WHERE deptno=:dno' USING v_deptno ;

    FETCH cur_emp BULK COLLECT INTO v_emprow ;

    CLOSE cur_emp ;

    FOR x IN 1 .. v_emprow.COUNT LOOP

    DBMS_OUTPUT.put_line('雇员编号:' || v_emprow(x).empno || ',姓名:' || v_emprow(x).ename || ',职位:' || v_emprow(x).job) ;

    END LOOP ;

    END ;

    /

     

    范例:查看DBMS_SQL包定义

    SELECT *

    FROM all_source

    WHERE type='PACKAGE' AND name='DBMS_SQL'  ;

    范例:通过DBMS_SQL包查询数据

    DECLARE  

    v_sql_statement VARCHAR2(200) ;

    v_cid NUMBER ; -- 保存游标ID,以方便关闭

    v_ename emp.ename%TYPE ;

    v_job emp.job%TYPE ;

    v_sal emp.sal%TYPE ;

    v_stat NUMBER ;

    v_deptno emp.deptno%TYPE := 10 ; -- 部门编号

    BEGIN

    v_cid := DBMS_SQL.open_cursor ; -- 打开游标

    v_sql_statement := 'SELECT ename,job,sal FROM emp WHERE deptno=:dno' ;

    DBMS_SQL.parse(v_cid , v_sql_statement ,DBMS_SQL.native) ;

    DBMS_SQL.define_column(v_cid , 1 , v_ename, 10) ; -- 定义OUT模式变量

    DBMS_SQL.define_column(v_cid , 2 , v_job, 9) ; -- 定义OUT模式变量

    DBMS_SQL.define_column(v_cid , 3 , v_sal) ; -- 定义OUT模式变量

    DBMS_SQL.bind_variable(v_cid, ':dno', v_deptno); --绑定变量

    v_stat := DBMS_SQL.execute(v_cid) ; -- 执行游标,返回更新行数

    LOOP

    EXIT WHEN DBMS_SQL.fetch_rows(v_cid)=0 ;

    DBMS_SQL.column_value(v_cid , 1 , v_ename) ;

    DBMS_SQL.column_value(v_cid , 2 , v_job) ;

    DBMS_SQL.column_value(v_cid , 3 , v_sal) ;

    DBMS_OUTPUT.put_line('雇员姓名:' || v_ename || ',职位:' || v_job || ',薪金:' || v_sal) ;

    END LOOP ;

    DBMS_SQL.close_cursor(v_cid) ; -- 关闭游标

    END ;

    /

    DECLARE  

    v_sql_statement VARCHAR2(200) ;

    v_cid NUMBER ; -- 保存游标ID,以方便关闭

    v_comm emp.comm%TYPE :=500 ;

    v_empno emp.empno%TYPE := 7369 ;

    v_stat NUMBER ;

    BEGIN

    v_cid := DBMS_SQL.open_cursor ; -- 打开游标

    v_sql_statement := 'UPDATE emp SET comm=:ec WHERE empno=:eno' ;

    DBMS_SQL.parse(v_cid , v_sql_statement ,DBMS_SQL.native) ;

    DBMS_SQL.bind_variable(v_cid, ':ec', v_comm); --绑定变量

    DBMS_SQL.bind_variable(v_cid, ':eno', v_empno); --绑定变量

    v_stat := DBMS_SQL.execute(v_cid) ; -- 执行游标,返回更新行数

    DBMS_OUTPUT.put_line('更新行数为:' || v_stat) ;

    DBMS_SQL.close_cursor(v_cid) ; -- 关闭游标

    END ;

    /

  • 相关阅读:
    python有哪些关键字?让他自己“吐”出来!
    jquery获取表单元素与回显
    前端开发笔记--flex布局
    Vue-Quill-Editor回显不显示空格的处理办法
    react项目中antd组件库的使用需要注意的问题
    React Native 列表的总结
    是时候了解React Native了
    Android 整合实现简单易用、功能强大的RecyclerView
    linux centos 一键安装环境
    推翻自己和过往,重学自定义View
  • 原文地址:https://www.cnblogs.com/doudouxiaoye/p/5804379.html
Copyright © 2020-2023  润新知