errorbeep@home:~$

Learning Sql

当前连接数

select count(*) from v$process;
--修改最大连接数(把processes改成500就好了)
alter system set processes = 500 scope = spfile;
--select value from v$parameter where name = 'processes';
--COMMIT;
--允许最大连接数 (默认是100)
select value from v$parameter where name = 'processes';

查询session信息

SHOW PARAMETER SESSION;

查询processes信息

SHOW PARAMETER PROCESS;

创建表空间

CREATE TABLESPACE TempSpace DATAFILE 'E:\Sorcery\Necromancy\DataBase\data\TempSpace_DATA.DBF' SIZE 50M;

创建用户

CREATE USER user1 IDENTIFIED BY user1 DEFAULT TABLESPACE TempSpace;

授予用户DBA权限

GRANT DBA TO user1;

创建表

CREATE TABLE Temp
(
  sno CHAR(10) PRIMARY KEY,
  sname VARCHAR(13) UNIQUE,
  gender CHAR(3) CHECK(gender in ('男', '女')),
  dept VARCHAR(14) NOT NULL,
  remarks VARCHAR(30) DEFAULT('三好学生')
);
SELECT * FROM Temp;
CREATE TABLE ScoreTable
(
  sno CHAR(10) PRIMARY KEY, --REFERENCES Temp(sno),
  cno CHAR(4) DEFAULT('0001'),
  score INT DEFAULT(0)
  --CONSTRAINT cno_ScoreTable FOREIGN KEY(cno)REFERENCES Subject(nationkey)
  
  --PRIMARY KEY(sno,cno),/*定义主码*/
  -- FOREIGN KEY(sno)REFERENCES Temp(sno),
  -- FOREIGN KEY(cno)REFERENCES Subject(cno)
);
INSERT INTO ScoreTable VALUES(189074010, 0001, 88);
SELECT * FROM ScoreTable ;
UPDATE ScoreTable SET cno = '0001';
CREATE TABLE Subject
(
  cno CHAR(4) PRIMARY KEY,
  cname VARCHAR2(10) UNIQUE
);
ALTER TABLE Subject MODIFY cname VARCHAR2(30);
INSERT INTO Subject VALUES('0008', '离散数学');
SELECT * FROM Subject;

参照完整性

ALTER TABLE ScoreTable ADD CONSTRAINT sno_const FOREIGN KEY(sno) REFERENCES Temp(sno); 
ALTER TABLE ScoreTable ADD CONSTRAINT cno_const FOREIGN KEY(cno) REFERENCES Subject(cno);
-- ALTER TABLE ScoreTable DROP CONSTRAINT sno_const;

修改基本表

ALTER TABLE Temp ADD CONSTRAINT temp_dept_uni UNIQUE(dept);-- 增加约束条件
ALTER TABLE Temp DROP CONSTRAINT temp_dept_uni;-- 删除约束条件
ALTER TABLE Subject ADD ctime INT DEFAULT(40);-- 增加属性
ALTER TABLE Temp ADD resume VARCHAR(30);-- 增加属性
ALTER TABLE Temp DROP COLUMN resume;-- 删除属性
ALTER TABLE ScoreTable ADD no INT;
ALTER TABLE ScoreTable DROP COLUMN no;
-- SELECT * FROM ScoreTable;
ALTER TABLE ScoreTable ADD ID INT ;
ALTER TABLE ScoreTable DROP PRIMARY KEY;
ALTER TABLE ScoreTable ADD CONSTRAINT st_prk PRIMARY KEY(ID);
ALTER TABLE Temp MODIFY sname VARCHAR2(14; -- 这样不会去除sname的唯一约束条件
-- 如下写法是错误的:
-- ALTER TABLE Temp MODIFY sname VARCHAR2(14)UNIQUE;

删除基本表

-- DROP TABLE Temp;

向表中插入数据

INSERT INTO Temp VALUES('189074004', 'Jim', '男', '机械', '三坏学生');-- 单行插入
INSERT INTO Temp(sno, sname, dept) VALUES('189074000', 'Jenny', '机械');
INSERT INTO Temp SELECT * FROM Stu;-- 多行插入(表间拷贝)
CREATE TABLE XS AS SELECT * FROM TEMP;-- 创建表XS并插入表Temp中的所有数据

更改记录

UPDATE Temp SET remarks = '三好学生';-- 修改所有记录
UPDATE Temp SET remarks = '三坏学生' WHERE sno = '189074005'; 
UPDATE Temp SET remarks = '三坏学生', dept = '软件工程' WHERE sno = '189074006'; 
UPDATE ScoreTable SET ID = to_number(sno)  - 189074000;
SELECT * FROM ScoreTable;

删除记录

DELETE FROM Temp WHERE dept = '机械';

单表查询

SELECT 3 + 5 FROM DUAL;-- 表达式求值
SELECT * FROM Temp;
SELECT sno, sname FROM Temp;
SELECT sno AS 学号, sname AS 姓名 FROM Temp;
SELECT dept FROM Temp;
SELECT DISTINCT dept FROM Temp;-- 投影-- DISTINCT 必须放在开头
SELECT DISTINCT sno, score FROM ScoreTable;-- 根据字段sno和score去重
SELECT sno, credit FROM Temp WHERE credit > 50;
SELECT sno, credit FROM Temp WHERE credit BETWEEN 55 AND 57;
SELECT sno, credit FROM Temp WHERE credit NOT BETWEEN 55 AND 57;
SELECT sno, dept FROM Temp WHERE dept IN('计算机', '电气');
SELECT sno, dept FROM Temp WHERE dept NOT IN('计算机', '电气');

模糊查询

SELECT sno, sname FROM Temp WHERE sname LIKE '%m%';
SELECT sno, sname FROM Temp WHERE sname LIKE '%m_';
SELECT sno, sname FROM Temp WHERE sname LIKE 'ABC\_DEF' ESCAPE '\';
--  在mysql中不用加“ESCAPE '\'”
 
SELECT sno, credit FROM Temp WHERE credit IS NULL;
SELECT sno, credit FROM Temp WHERE credit IS NOT NULL;

组函数

SELECT COUNT(*) AS 总人数 FROM Temp;
SELECT COUNT(DISTINCT dept) AS 院系数 FROM Temp;
SELECT AVG(credit) AS 电气专业平均学分 FROM Temp WHERE dept = '电气';
SELECT MAX(credit) AS 最高学分 FROM Temp;
SELECT MIN(credit) AS 最低学分 FROM Temp;-- 不包括NULL
SELECT SUM(credit) AS 学分之和 FROM Temp;

分组查询

SELECT dept AS 系别, COUNT(*) AS 人数 FROM Temp GROUP BY dept;
SELECT dept AS 系别, AVG(credit) AS 均分 FROM Temp GROUP BY dept;

HAVING子句

-- WHERE作用于基本表或视图,从中选择满足条件的元组;
-- HAVING短语作用于组,从中选择满足条件的组。 
SELECT dept, COUNT(*) FROM Temp GROUP BY dept HAVING COUNT(*) > 2;

排序

SELECT * FROM Temp ORDER BY sno ASC, class DESC;

多表查询

无条件连接

SELECT * FROM Temp, ScoreTable;
SELECT ctime FROM Subject a,ScoreTable b WHERE a.cno = b.cno AND b.sno = '189074004';

笛卡尔积

SELECT * FROM Temp CROSS JOIN ScoreTable;

theta连接

SELECT Temp.*, ScoreTable.* FROM Temp join ScoreTable ON Temp.sno = ScoreTable.sno;
SELECT * FROM Temp JOIN ScoreTable ON Temp.sno = ScoreTable.sno;
SELECT * FROM Temp JOIN ScoreTable ON Temp.sno = ScoreTable.sno WHERE dept = '计算机' ORDER BY Temp.sno ASC;
SELECT * FROM Temp a JOIN ScoreTable b ON a.sno = b.sno JOIN Subject c ON b.cno = c.cno WHERE b.score >= 80;

自连接

SELECT * FROM ScoreTable a JOIN ScoreTable b ON a.sno <> b.sno WHERE b.sno = '189074001' AND a.score > b.score;
SELECT * FROM Temp a JOIN Temp b ON a.sno <> b.sno WHERE a.sname = 'Tom' AND a.credit < b.credit;
-- 与以下语句结果相同:SELECT * FROM Temp a, Temp b WHERE a.sname = 'Tom' AND a.credit < b.credit;

右连接

右(外)连接,右表的记录将会全部表示出来,而左表只会显示符合搜索条件的记录。左表记录不足的地方均为NULL。左(外)连接与之相反。

SELECT * FROM ScoreTable a RIGHT JOIN Temp b ON a.sno = b.sno WHERE a.sno is NULL;

自然连接

SELECT * FROM Temp JOIN ScoreTable USING(sno);
SELECT * FROM Temp NATURAL JOIN ScoreTable;
SELECT * FROM Temp NATURAL JOIN ScoreTable NATURAL JOIN Subject;
-- NATURAL 联接中使用的列不能有限定词
-- 误:SELECT * FROM Temp a NATURAL JOIN ScoreTable b NATURAL JOIN Subject c WHERE a.sno = '189074001';
-- 误:SELECT * FROM Temp a NATURAL JOIN ScoreTable b WHERE a.sno = '189074001';
-- 正:SELECT * FROM Temp a JOIN ScoreTable b ON a.sno = b.sno JOIN Subject c ON b.cno = c.cno WHERE a.sno = '189074001';

子查询

子查询放在WHERE子句中:

SELECT ctime FROM Subject WHERE Subject.cno = (SELECT cno FROM ScoreTable WHERE ScoreTable.sno = '189074004');-- 逻辑清晰但速度慢
-- 同:SELECT ctime FROM Subject a, ScoreTable b WHERE a.cno = b.cno AND b.sno = '189074004';
SELECT * FROM Temp WHERE sno IN (SELECT sno FROM ScoreTable WHERE cno  = (SELECT cno FROM Subject WHERE cname = '大学英语'));
-- 同:SELECT * FROM Temp a, ScoreTable b, Subject c WHERE a.sno = b.sno AND b.cno = c.cno AND c.cname = '大学英语'; 
-- 同:SELECT * FROM Temp a JOIN ScoreTable b ON a.sno = b.sno JOIN Subject c ON b.cno = c.cno WHERE cname = '大学英语';
-- 同:SELECT * FROM Temp WHERE sno IN (SELECT sno FROM ScoreTable WHERE cno IN (SELECT cno FROM Subject WHERE cname = '大学英语'));
SELECT * FROM ScoreTable WHERE score > (SELECT MAX(score) FROM ScoreTable WHERE cno = '0002');
SELECT * FROM ScoreTable WHERE score > ALL (SELECT score FROM ScoreTable WHERE cno = '0002');
SELECT * FROM ScoreTable WHERE score < (SELECT MIN(score) FROM ScoreTable WHERE cno = '0001');
SELECT * FROM ScoreTable WHERE score < ALL (SELECT score FROM ScoreTable WHERE cno = '0001');
SELECT * FROM ScoreTable WHERE score > ANY (SELECT score FROM ScoreTable WHERE cno = '0002');
--  == 
SELECT * FROM ScoreTable WHERE score > SOME (SELECT score FROM ScoreTable WHERE cno = '0002');

将子查询放在SELECT中:

SELECT sno, score, (SELECT MAX(score) FROM ScoreTable)MaxSocre FROM ScoreTable;

将子查询放在FROM中:

Oracle:

SELECT * FROM (SELECT * FROM ScoreTable ORDER BY score DESC) WHERE ROWNUM <= 5;-- 求成绩的前5名
-- 误:SELECT * FROM ScoreTable WHERE ROWNUM <= 5 ORDER BY score DESC;

mysql:

--  mysql  Ver 8.0.21-0ubuntu0.20.04.4 for Linux on x86_64 ((Ubuntu))
--  当前版本mysql中没有ROWNUM, 可以使用如下方法实现ROWNUM:
SELECT @ROWNUM := @ROWNUM + 1 AS ROWNUM, sno, score FROM (SELECT @ROWNUM := 0)r, ScoreTable;
--  以@符号开头的变量是会话变量。直到会话结束前它可用和可访问。
-- 因此该例的实现为:
SELECT * FROM (SELECT @ROWNUM := @ROWNUM + 1 AS ROWNUM, sno, score FROM (SELECT @ROWNUM := 0)r, ScoreTable ORDER BY score DESC)sc WHERE ROWNUM <= 5;-- 求成绩的前5名

相关子查询

所有的子查询可以分为两类,即相关子查询和非相关子查询

非相关子查询是独立于外部查询的子查询,子查询总共执行一次,执行完毕后将值传递给外部查询。 相关子查询的执行依赖于外部查询的数据,外部查询执行一行,子查询就执行一次。执行查询的时候先取得外层查询的一个属性值,然后执行与此属性值相关的子查询,执行完毕后再取得外层父查询的下一个值,依次再来重复执行子查询;故非相关子查询比相关子查询效率高。

SELECT sno, score FROM ScoreTable WHERE EXISTS(SELECT * FROM Temp WHERE sno = ScoreTable.sno AND sno = '189074001');
--  同:
SELECT DISTINCT sno, gender, dept, remarks, sname, credit FROM (SELECT a.* FROM Temp a LEFT JOIN ScoreTable b ON a.sno = b.sno WHERE b.sno IS NOT NULL)t;

SELECT * FROM Temp WHERE NOT EXISTS (SELECT * FROM Subject WHERE NOT EXISTS (SELECT * FROM ScoreTable WHERE Temp.sno = sno AND cno = Subject.cno));

传统集合运算

并运算

SELECT sno, cno FROM ScoreTable WHERE cno = '0001' UNION SELECT sno, cno FROM ScoreTable WHERE cno = '0002';
-- 同:SELECT sno, cno FROM ScoreTable WHERE cno IN ('0001', '0002');
SELECT sno FROM ScoreTable UNION SELECT sno FROM Temp;
  • UNION ALL 不去重
SELECT sno FROM Temp WHERE sno IN ('189074000', '189074001') 
UNION ALL
SELECT sno FROM Temp WHERE sno IN ('189074000', '189074002');

交运算

  • mysql只支持UNION运算,不支持INTERSECT运算
SELECT sno FROM ScoreTable WHERE cno = '0001' INTERSECT SELECT sno FROM ScoreTable WHERE cno = '0002';
-- 同:SELECT sno FROM ScoreTable WHERE cno = '0001' AND sno IN (SELECT sno FROM ScoreTable WHERE cno = '0002'); -- 在mysql中可以这样实现交运算

差运算

  • mysql中不支持MINUS运算
SELECT sno FROM Temp MINUS SELECT sno FROM ScoreTable WHERE cno = '0002';
-- ORACLE中用MINUS,SQL SERVER中用EXCEPT

查询比计算机专业女生人数还少的专业及女生人数

SELECT dept, girl 
FROM 
(
    SELECT dept, COUNT(CASE WHEN gender = '女' THEN '1' END) girl 
    FROM Temp 
    GROUP BY dept 
)
WHERE girl < 
(
       SELECT girl 
       FROM 
       (
          SELECT dept, COUNT(CASE WHEN gender = '女' THEN '1' END) girl 
          FROM Temp 
          GROUP BY dept 
       )
      WHERE dept = '计算机'
                                        
);

--  以下代码不正确(当存在某专业女生人数为0时...)
SELECT dept, COUNT(*) FROM Temp WHERE gender = '女' GROUP BY dept HAVING COUNT(*) <= (SELECT COUNT(*)FROM Temp WHERE dept = '计算机' AND gender = '女');

SELECT DISTINCT dept 
FROM Temp 
MINUS 
(
    SELECT dept 
    FROM Temp 
    WHERE gender = '女' 
    GROUP BY dept 
    HAVING COUNT(*) >= (
        SELECT COUNT(*)
        FROM Temp 
        WHERE dept = '计算机' AND gender = '女'
    )
);

分页查询

--  Oracle:
SELECT * FROM (SELECT ROWNUM rn, sno, sname, dept,  credit FROM Temp WHERE ROWNUM <= currentPage * pageSize)tmp WHERE rn > (currentPage -1) * pageSize;

--  mysql:
SELECT * FROM (SELECT @ROWNUM := @ROWNUM + 1 AS ROWNUM, sno, sname, credit FROM (SELECT @ROWNUM := 0)r, Temp)page WHERE ROWNUM BETWEEN ((currentPage - 1) * pageSize + 1) AND (currentPage * pageSize);

索引

CREATE INDEX scoreT_score_idx ON ScoreTable(score);
-- CREATE UNIQUE INDEX temp_sname_uniq_idx ON Temp(sname);
CREATE INDEX scoreT_idx ON ScoreTable(sno, cno);-- 复合索引
CREATE INDEX sub_cn_ct_idx ON Subject(cno ASC, ctime DESC);-- 指定索引值的排列顺序

视图

CREATE OR REPLACE VIEW temp_CS_view
AS 
SELECT * FROM Temp WHERE dept = '计算机';
CREATE OR REPLACE VIEW score_sno_avg_viewsno, avg_score-- 要使用别名
AS
SELECT sno, AVG(score) FROM ScoreTable GROUP BY sno;

使用视图

SELECT * FROM score_sno_avg_view WHERE avg_score > 85;
-- UPDATE score_sno_avg_view SET sno = 100 WHERE avg_score = 88;-- 此视图的数据操纵操作非法
UPDATE temp_CS_view SET sname = 'Amilia' WHERE sname = 'Amy';-- 1行已更新。

删除视图

DROP view temp_CS_view;

同义词

  • mysql中没有synonym
CREATE OR REPLACE PUBLIC SYNONYM score_s_a FOR score_sno_avg_view;-- 公有同义词
CREATE OR REPLACE SYNONYM score_sa FOR score_sno_avg_view;-- 私有同义词

序列

  • mysql中无SEQUENCE
CREATE SEQUENCE id_seq
START WITH 189074012
INCREMENT BY 1
MAXVALUE 189074999
CACHE 50;

INSERT INTO Temp VALUES(id_seq.NEXTVAL, 'Larry', '男', '计算机', '三无学生', '10', '1');-- 189074012
SELECT id_seq.CURRVAL FROM DUAL;
SELECT id_seq.NEXTVAL FROM DUAL;
INSERT INTO Temp VALUES(id_seq.NEXTVAL, 'Harry', '男', '计算机', '三沙学生', '15', '1');-- 189074014

删除序列

DROP SEQUENCE id_seq;

PL-SQL编程

  • MySQL不支持anonymous code block
/
SET SERVEROUTPUT ON;
DECLARE
  stuno Temp.sno%TYPE;
  stuname Temp.sname%TYPE;
BEGIN
  SELECT sno, sname INTO stuno, stuname FROM Temp WHERE sno = '189074005';
  DBMS_OUTPUT.PUT_LINE(stuno||stuname);
END;
/
SET SERVEROUTPUT ON;
DECLARE
  stu Temp%ROWTYPE;
BEGIN
  SELECT *  INTO stu FROM Temp WHERE sno = '189074005';
  DBMS_OUTPUT.PUT_LINE(stu.sno||stu.sname||stu.dept);
END;
/
set SERVEROUTPUT ON;
DECLARE
    n number;
    result number;
BEGIN
    n:=0;   result:=0;
    while n<=100 loop
        result:=result+n;
        n:=n+1;
    end loop;
    dbms_output.put_line('结果是'||result);
END;
/

PROCEDURE 存储过程

创建存储过程(Oracle)

CREATE OR REPLACE PROCEDURE sp_calcsum1
as
    n number;   result number;
BEGIN
    n:=0;   result:=0;
    while n<=100 loop
        result:=result+n;
        n:=n+1;
    end loop;
    dbms_output.put_line('结果是'||result);
END;
/*
   在view(视图)中,只能使用as;
   在corsor(游标)中,只能使用is;
   对于procedure(存储过程), function(函数), package(程序包)来说,as和is没有区别。
*/

执行存储过程(Oracle)

execute sp_calcsum1;

BEGIN 
sp_calcsum1;
END;
/
CREATE OR REPLACE PROCEDURE del_sc(stuNo IN Temp.sno%TYPE, crsNo IN Subject.cno%TYPE)
IS /*不能加DECLARE*/
BEGIN 
    DELETE FROM ScoreTable WHERE sno = stuNo AND cno = crsNo;
EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
        DBMS_OUTPUT.put_line('没找到数据!');
    WHEN OTHERS THEN
        DBMS_OUTPUT.put_line('产生异常!');
END;        
/
EXECUTE del_sc('189074000', '0008');
SELECT * FROM ScoreTable;

/
CREATE OR REPLACE PROCEDURE sel_score(stuNo IN Temp.sno%TYPE, crsNo IN Subject.cno%TYPE, sco OUT ScoreTable.score%TYPE)
IS
BEGIN
    SELECT score INTO sco FROM ScoreTable WHERE stuNo = sno AND crsNo = cno;
EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
        DBMS_OUTPUT.put_line('没找到数据!');
    WHEN OTHERS THEN
        DBMS_OUTPUT.put_line('产生异常!'); 
END;    
/

SET SERVEROUTPUT ON;
DECLARE
  score ScoreTable.score%TYPE;
BEGIN 
  sel_score('189074000', '0008', score);/*不需要EXECUTE*/
  DBMS_OUTPUT.PUT_LINE(score);
END;
/

创建存储过程(Mysql)

DELIMITER $$

CREATE PROCEDURE calcsum(OUT sum INT)
BEGIN 
   DECLARE n INT;
   SET n = 0;
   SET sum = 0;
   WHILE n <= 100 do
      SET sum = sum + n;
      SET n = n + 1;
   END WHILE;
END;
$$

执行存储过程(Mysql)

DELIMITER ;
SET @sum = 0;
CALL calcsum(@sum);
 

FUNCTION


/
CREATE OR REPLACE FUNCTION f_calcsum(n number) return int
as
    i number:=0;
    result number:=0;
BEGIN
    while i<=n loop
        result:=result+n;
        i:=i+1;
    end loop;
    return result;
END;
/
DECLARE
  result int:=f_calcsum(10);
BEGIN
  dbms_output.put_line('结果是'||result);
END;
/

游标

利用游标变量循环

SET SERVEROUTPUT ON;
DECLARE
  stu Temp%ROWTYPE;
  CURSOR cur_tmp IS SELECT * FROM Temp;
BEGIN
  OPEN cur_tmp;
  LOOP                  
    FETCH cur_tmp INTO stu;
    EXIT WHEN cur_tmp%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE(stu.sno||stu.sname);
  END LOOP;
CLOSE cur_tmp;
END;   

FOR循环

/
SET SERVEROUTPUT ON;
DECLARE
  CURSOR cur_tmp IS SELECT * FROM Temp;
BEGIN
-- 无需手动打开关闭游标
  FOR stu IN cur_tmp LOOP
  DBMS_OUTPUT.PUT_LINE(stu.sno||stu.sname);
  END LOOP;
END;
/

/
SET SERVEROUTPUT ON;
BEGIN
  FOR stu IN (SELECT * FROM Temp) LOOP
  DBMS_OUTPUT.PUT_LINE(stu.sno||stu.sname);
  END LOOP; 
END;
/
SET SERVEROUTPUT ON;
BEGIN 
    FOR stu IN (SELECT * FROM Temp) LOOP
        IF stu.sname  LIKE '%J%' THEN
            DBMS_OUTPUT.PUT_LINE(stu.sname);
        END IF;
    END LOOP;
END;    
/
SET SERVEROUTPUT ON;
CREATE OR REPLACE PROCEDURE find_name(name Temp.sname%TYPE)
AS
BEGIN
    FOR stu IN (SELECT * FROM Temp) LOOP
        IF stu.sname LIKE '%'||name||'%' THEN 
            DBMS_OUTPUT.PUT_LINE(stu.sname);
        END IF;
    END LOOP;
END;    
/
EXECUTE find_name('J');
/

隐式游标

SET SERVEROUTPUT ON;
BEGIN
  UPDATE Temp SET credit = credit + 1 WHERE credit IS NOT NULL;
  IF SQL%NOTFOUND THEN   
    DBMS_OUTPUT.PUT_LINE('没有记录被更改!');
  ELSE
    DBMS_OUTPUT.PUT_LINE('更改了'||SQL%ROWCOUNT||'条记录。');
  END IF;
END;
/

异常处理

/
DECLARE
    stuno Temp.sno%TYPE;
    stuname Temp.sname%TYPE;
BEGIN
    SELECT sno,sname INTO stuno,stuname FROM  Temp ;
    DBMS_OUTPUT.PUT_LINE(stuno||stuname);
EXCEPTION
    WHEN no_data_found THEN
      DBMS_OUTPUT.PUT_LINE('数据没找到');
    WHEN too_many_rows THEN
      DBMS_OUTPUT.PUT_LINE('结果集超过一行');
END;
/
DECLARE
    null_exp EXCEPTION;
    stucj Subject%ROWTYPE;
BEGIN
  stucj.cname:='001241'; stucj.cno:='206';
  INSERT INTO Subject VALUES(stucj.cno,stucj.cname,stucj.ctime);
  IF stucj.ctime IS NULL THEN   
   RAISE null_exp;   
  END IF;
EXCEPTION
    WHEN null_exp THEN
      DBMS_OUTPUT.PUT_LINE('成绩不能为空值');
      ROLLBACK;
    WHEN others THEN
      DBMS_OUTPUT.PUT_LINE('其他异常');
END;
/

触发器

CREATE TABLE ScoreT_log
(
    operate_type varchar2(20),   
    operate_date date,
    operate_user varchar2(20)
 );
/
CREATE OR REPLACE TRIGGER tri_ScoreT BEFORE INSERT OR DELETE OR UPDATE ON ScoreTable
DECLARE 
    operate_type varchar2(20);
BEGIN
    IF INSERTING THEN 
        operate_type := 'INSERT';
    ELSIF DELETING THEN 
        operate_type := 'DELETE';
    ELSE
        operate_type := 'UPDATE';
    END IF;
    INSERT INTO ScoreT_log VALUES(operate_type, sysdate, ora_login_user );
END;    
/
UPDATE ScoreTable SET score = 75 WHERE sno = '189074000' AND cno = '0001';
-- SELECT * FROM ScoreT_log;
/
CREATE OR REPLACE TRIGGER tri_del_tmp AFTER DELETE ON Temp
FOR EACH ROW 
BEGIN
    DELETE FROM ScoreTable WHERE sno = :old.sno;
END;
/

DELETE FROM Temp WHERE sno = '189074011';
-- SELECT * FROM ScoreTable;
-- SELECT * FROM ScoreT_log;

事务提交与回退

SHOW AUTOCOMMIT;
SET AUTOCOMMIT ON;
SET AUTOCOMMIT OFF;
-- 某些SQL语句(DDL语句, DCL语句, ),在它们被执行时会生成隐含的COMMIT命令,将会马上导致事务提交。

-- 只撤销一部分事务  
UPDATE Temp SET remarks = '三坏学生' WHERE sno = '189074005'; 
SAVEPOINT t;
UPDATE Temp SET remarks = '三坏学生', dept = '软件工程' WHERE sno = '189074006'; 
ROLLBACK TO t;

JDBC

JDBC execute

package priv.Matrix.mine;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Execute 
{
    public static void main(String[] args)
    {

        String conStr = "jdbc:oracle:thin:@localhost:1521:xe";
        String username = "user1";
        String password = "user1";

        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;

        String sql = "CREATE TABLE tmp"
            + "("
            + "     id varchar2(20),"
            + "     info varchar2(30)"
            + ")";


        try
        {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        }
        catch (ClassNotFoundException e)
        {
            --  TODO Auto-generated catch block
            e.printStackTrace();
        }

        try
        {
            con = DriverManager.getConnection(conStr, username, password);
            stmt = con.createStatement();
            boolean isResultSet = stmt.execute(sql);
            int count = 0;
            int rowAffected = 0;
            while(true)
            {
                if(isResultSet)
                {
                    count++;
                    System.out.println("ResultSet:" + count);
                    rs = stmt.getResultSet();
                    while(rs.next())
                    {
                        System.out.println(rs.getString("id") + "\t" + rs.getString("info"));
                    }

                }
                else
                {
                    rowAffected = stmt.getUpdateCount();
                    System.out.println("row affected:" + rowAffected);
                    if(rowAffected == -1)
                    {
                        break;
                    }

                }
                stmt.getMoreResults();
            }

        }
        catch (SQLException e)
        {
            --  TODO Auto-generated catch block
            e.printStackTrace();
        }

    }


}

JDBC executeBatch

package priv.Matrix.mine;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class Execute 
{
    public static void main(String[] args)
    {

        String conStr = "jdbc:oracle:thin:@localhost:1521:xe";
        String username = "user1";
        String password = "user1";

        Connection con = null;
        Statement stmt = null;

        String createTab = ("CREATE TABLE tmp"
                + "("
                + "     id varchar2(20),"
                + "     info varchar2(30)"
                + ")");

        int[] rowAffected = new int[3];

        try
        {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        }
        catch (ClassNotFoundException e)
        {
            --  TODO Auto-generated catch block
            e.printStackTrace();
        }

        try
        {
            con = DriverManager.getConnection(conStr, username, password);
            stmt = con.createStatement();

            stmt.executeUpdate(createTab);

            stmt.addBatch("INSERT INTO tmp VALUES('10001', 'first_info')");
            stmt.addBatch("UPDATE tmp SET info = 'second_info' WHERE id = '10001'");
            stmt.addBatch("DELETE FROM tmp WHERE id = '10001'");

            rowAffected = stmt.executeBatch();

            for(int i = 0; i < 3; i++)
            {
                System.out.println("row affected:" + rowAffected[i]);
            }

        }
        catch (SQLException e)
        {
            --  TODO Auto-generated catch block
            e.printStackTrace();
        }

    }


}

JDBC PreparedStatement

package priv.Matrix.mine;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Execute 
{
    public static void main(String[] args)
    {

        String conStr = "jdbc:oracle:thin:@localhost:1521:xe";
        String username = "user1";
        String password = "user1";

        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;

        String createTab = ("CREATE TABLE tmp"
                + "("
                + "     id varchar2(20),"
                + "     info varchar2(30)"
                + ")");


        try
        {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        }
        catch (ClassNotFoundException e)
        {
            --  TODO Auto-generated catch block
            e.printStackTrace();
        }

        try
        {
            con = DriverManager.getConnection(conStr, username, password);

            stmt = con.createStatement();
            stmt.executeUpdate(createTab);

            PreparedStatement pstmtInsert = con.prepareStatement("INSERT INTO tmp VALUES(?, ?)");
            PreparedStatement pstmtSelect = con.prepareStatement("SELECT * FROM tmp WHERE id = ?");
            PreparedStatement pstmtUpdate = con.prepareStatement("UPDATE tmp SET info = ? WHERE id = ?");
            PreparedStatement pstmtDelete = con.prepareStatement("DELETE FROM tmp WHERE id = ?");

           -- 该字符串不需要加单引号(')"INSERT INTO tmp VALUES('?', '?')"是错的  
            pstmtInsert.setString(1, "10001");
            pstmtInsert.setString(2, "first info");
            pstmtInsert.executeUpdate();

            pstmtSelect.setString(1, "10001");
            rs = pstmtSelect.executeQuery();
            while(rs.next())
            {
                System.out.println(rs.getString("id") + "\t" + rs.getString("info"));
            }


            pstmtUpdate.setString(1, "second info");
            pstmtUpdate.setString(2, "10001");
            pstmtUpdate.executeUpdate();

            pstmtDelete.setString(1, "10001");
            pstmtDelete.executeUpdate();





        }
        catch (SQLException e)
        {
            --  TODO Auto-generated catch block
            e.printStackTrace();
        }

    }


}