ステレオタイプの神託

Oracleデータベース管理

plsqlはOracleサーバーに接続します

用户:scott
密码:自己设置的密码
连接的数据库:orcl

デフォルトでは、scott ユーザーには 4 つのテーブルしかありません

emp、ボーナス、デプ、サルグレード

画像-20220111194754524

画像-20220111195024197

ユーザー管理

ユーザーアカウントを作成する

ユーザーアカウントの表示

Oracle の概要リソース

モデル

テーブルスペース

権限管理

補足 SQL 予備

DML: データ操作言語 データ操作言語

DDL: データ定義言語 データ定義言語

DCL: データ制御言語データ制御言語

DDL

DDL は、次のようにデータベース オブジェクトの作成、変更、削除など、データベースの構造を定義するために使用されます。

  • CREATE TABLE: データベーステーブルを作成します。
  • ALTER TABLE: テーブル構造の変更、追加、削除、列の長さの変更
  • DROP TABLE: テーブルを削除します
  • CREATE INDEX: テーブルにインデックスを作成します。
  • DROP INDEX: インデックスを削除します。

DML

DML は、次の操作を含むデータ レコードのクエリと変更に使用されます。

  • INSERT: データベースにデータを追加します
  • UPDATE: データベース内のデータを変更する
  • DELETE: データベース内のデータを削除します
  • SELECT: クエリデータを選択します

その中で、select は SQL 言語の基礎であり、最も重要です

DCL

DCL は、次の操作を含むデータベース アクセスを制御するために使用されます。

  • GRANT: アクセスを許可する
  • REVOKE: アクセスを取り消します
  • COMMIT: トランザクション処理をコミットします。
  • ROLLBACK: トランザクション処理のロールバック
  • セーブポイント: セーブポイントを設定します
  • LOCK: データベースの特定の部分をロックします。

基本的なSQL文

基本的な SELECT ステートメント

構文: SELECT * |{ [DISTINCT] column | expression [alias],...} FROM TABLE;

SELECT は選択する列を識別します

FROM はどのテーブルから選択するかを識別します

すべての列を選択する

SELECT * FROM EMP;

画像-20220111200943154

特定の列を選択する

SELECT EMPNO , ENAME FROM EMP ;

知らせ:

SQL 言語の大文字と小文字を区別しない

SQL は 1 行以上で記述できます

キーワードを省略したり分離したりすることはできません

通常、各文は別々の行に書く必要があります

インデントを使用してステートメントを読みやすくします

算術演算子

オペレーター 説明
+ 追加
- 減らす
* 取った
/ 削除
SELECT ENAME , SAL,SAL+100 FROM EMP ;

画像-20220111201618069

演算子の優先順位

  • 乗算と除算は加算と減算より優先されます
  • 同じ優先順位を持つ演算子は左から右に実行されます。
  • 括弧内の演算が最初に実行されます
SELECT ENAME , SAL , SAL*3+300 FROM emp;

画像-20220111202057011

括弧を使用する

SELECT ENAME , sal , 10 * (sal + 100) FROM EMP ;

画像-20220111202405842

nullを定義する

/*定义空值*/
SELECT ENAME , SAL ,COMM FROM EMP ;
  • null 値は、無効な、指定されていない、未知の、または予測できない値です。
  • Null はスペースや 0 ではありません

数学的演算における Null 値の使用

-- 包含空值的数学表达式的值都是空值
SELECT ENAME , 10*SAL*COMM FROM EMP ;

画像-20220111202845955

列の別名

  • 列の名前を変更する
  • 計算が簡単
  • 列名の直後に、列名と列名の間にキーワードを追加することもできます。asエイリアスに二重引用符を使用して、エイリアスにスペースが含まれるか、特殊文字が大文字と小文字を区別されるようにします。

エイリアスを使用する

SELECT ENAME NAME,SAL*10 sSL FROM emp;

画像-20220111203143356

ジョイナー

  • 列と列、列と文字を結合する
  • '||' を使用して表します
  • 列を結合するために使用できます
SELECT empno||ename empnew FROM emp;

画像-20220111203436927

  • 文字列SELECTには、リスト内の文字、数値、日付を指定できます。
  • 日付と文字は一重引用符でのみ使用できます
  • 行が返されるたびに、文字列が 1 回出力されます。
SELECT ename || 'is a ' || sal AS EMPDETAILS FROM emp;

画像-20220111203913556

繰り返し行

デフォルトでは、クエリは重複を含むすべての行を返します。

/*重复行*/
SELECT  JOB FROM emp;

/*删除重复行*/
SELECT DISTINCT job FROM emp;

SQL と SQL PLUS

SQL

  1. 言語
  2. ANSI規格
  3. キーワードは省略できません
  4. use文ナル値データベースのテーブル定義情報とテーブル内のデータ

SQLプラス

  1. 環境
  2. オラクルの機能の一つ
  3. キーワードは省略可能です
  4. コマンドはデータベース内のデータ値を変更できません
  5. 集中操作

テーブル構造を説明できる

SQL文を編集する

SQL文の実行

SQLをファイルに保存、SQL文の実行結果をファイルに保存

保存されたファイル内のステートメントを実行する

テキスト ファイルを SQL Plus 編集ウィンドウにロードします。

テーブル構造を表示

desc emp ;
describe emp ;

画像-20220111205030740

データのフィルターと並べ替え

クエリ内の行をフィルタリングする

フィルター

  • この句を使用してWHERE、条件を満たさない行をフィルタリングして除外します。
  • where 句の後に from 句が続く
SELECT *|{
   
   [DISTINCT] column|expression [alias]...} FROM TABLE WHERE conditions
SELECT * FROM emp WHERE sal > 200 ;

文字と日付

  • 文字と日付は一重引用符で囲まれます
  • 大文字と小文字が区別され、日付形式が区別されます
  • デフォルトの日付形式は DD-MONMonth-RR です。
SELECT * FROM emp WHERE ename = 'ALLEN' ;
SELECT * FROM emp  WHERE HIREDATE = '20-2月-1981';

比較演算

オペレーター 意味
= 等しい (== ではない) 注: 代入は =":= です
> 以上
>= 以上
< 未満
<= 以下
<> 等しくありません (!= の場合もあります)
SELECT * FROM emp WHERE sal <= 800 ;

その他の比較演算

オペレーター 意味
...と...の間 2 つの値の間
値のリストのいずれかと等しい
好き ファジークエリ
無効である 空の値

between 演算子を使用して、間隔内の値を表示します

SELECT * FROM emp WHERE sal BETWEEN 800 AND 1000 ;

IN キーワードを使用して値をリストに表示します

SELECT * FROM emp WHERE empno IN (7369,7370,7371) ;

好き

  • LIKE 操作を使用して類似の値を選択します
  • 選択基準には文字または数字を含めることができます。
  • % は、0 個以上の文字 (任意の数) を表します。
  • _は文字を表します。
SELECT * FROM emp WHERE empno LIKE '74%';
  • 「%」と「_」を一緒に使用する
SELECT * FROM emp WHERE empno LIKE '_4%';
  • 「%」および「_」記号は、ESCAPE 識別子を使用して選択できます。

特殊記号を避けるには、エスケープ文字を使用します。例えば

[%] を [%]、[_] を [_] に変換し、[ESCAPE ''] を追加します。

SELECT * FROM emp WHERE empno LIKE '73_%' ESCAPE '\';

ヌル

IS NULL を使用して null 値をチェックする

SELECT * FROM emp WHERE comm IS NULL ;

論理演算

オペレーター 意味
論理和集合
また 論理的または
いいえ 論理的に「いいえ」

両方の条件が true である必要があります

/*AND 逻辑与操作*/
SELECT * FROM emp WHERE sal >=800 AND comm IS NULL ;

また

両方の条件が true の場合のみ

SELECT * FROM emp WHERE sal >= 10000 OR empno LIKE '74%';

いいえ

論理否定演算

SELECT * FROM emp WHERE job NOT IN ('CLERK','MANAGER') ;

クエリで並べ替える

優先順位

優先順位
1 算術演算子
2 ジョイナー
3 コンパレータ
4 null 、のような、in
5
6 いいえ
7
8 また

注文方法

  • order by 句を使用した並べ替え
    • asc 昇順
    • 降順
  • order by 句は select ステートメントの最後にあります
# 降序
SELECT * FROM emp ORDER BY empno DESC;
# 升序
SELECT * FROM emp ORDER BY empno ;
# 按照别名排序
SELECT empno , sal*20+200 newsal FROM emp ORDER BY newsal DESC ;

一行関数

SQL のさまざまな種類の関数

画像-20220112210513335

2つの機能

  • 一行関数
  • 複数行の関数

一行関数

  1. データオブジェクトの操作
  2. パラメータを受け取って結果を返す
  3. 1行だけを変換する
  4. 行ごとに 1 つの結果を返します
  5. データ型を変換できる
  6. 入れ子にすることができます
  7. パラメータは列または値です。
function_name(arg1,arg2,...)
  • 一行関数
    • キャラクター
    • 価値
    • 日にち
    • 変換
    • 普遍的な

文字関数

ケースコントロール機能

LOWER,UPPER,INITCAP
関数名 機能説明 関数の構文
コンキャット 複数の文字列を 1 つの文字列に連結します concat(str1, str2,...) 戻り値はパラメータを連結して生成された文字列で、いずれかのパラメータが null の場合、戻り値は null になります。
サブストラ 文字インターセプト機能 形式 1: substr(string str, int a, int b); 1. string はインターセプトされる文字列 2. a はインターセプトされる文字列の開始位置 (注: a が 0 または 1 に等しい場合、開始位置は 0 または 1 から始まります)インターセプト) 3. b インターセプトされる文字列の長さ 形式 2: substr(string string, int a) ; 1. str インターセプトされる文字列 2. a は、 a番目の文字。
長さ 文字列の長さを示します 長さ(文字列)
命令 文字検索機能 INSTR( string, substring [, start_position [, th_appearance ] ] )string - 要搜索的字符串。字符串可以是CHAR,VARCHAR2,NCHAR,NVARCHAR2,CLOB或NCLOB等类型。 substring - 要在字符串(string)中搜索的子字符串。 子字符串可以是CHAR,VARCHAR2,NCHAR,NVARCHAR2,CLOB或NCLOB等类型。 start_position - 可选的。 在搜索将开始的字符串中的位置。 如果省略,则默认为1。字符串中的第一个位置为1.如果start_position为负数,INSTR函数会从字符串末尾开始计算start_position字符数,然后搜索字符串的开头。 nth_appearance - 可选的。 子串的第n个出现。 如果省略,则默认为1。 返回值:返回一个数字值。 字符串中的第一个位置是1。如果在字符串中找不到substring,那么INSTR函数将返回0。
LPAD 用于往源字符串的左侧填充一些字符 lpad( string1, padded_length, [ pad_string ] )tring1:源字符串padded_length:最终返回的字符串的长度,如果最终返回的字符串的长度比源字符串的小,那么此函数实际上对源串进行截断处理pad_string:用于填充的字符,可以不填,默认为空字符
RPAD 往源字符串的右侧填充一些字符 (字符串string1不能为空). RPAD( string1, padded_length [, pad_string] ) string1:源字符串. padded_length:要返回的字符长度。如果padded_length的值比原字符串的长度小,那么RPAD函数会对字符串进行截取处理。 pad_string:可以为空。用作填充的字符串。如果不填,默认为空格RPAD函数的返回值是字符串。
TRIM 用来去除一个字符串的开头或结尾(或两者)的字符 TRIM([ { { LEADING | TRAILING | BOTH } [ trim_character ] | trim_character } FROM ] trim_source ) leading 开头字符 trailing 结尾字符 both 开头和结尾字符 trim_character 去除的字符 trim_source 修剪源
REPLACE 用另外一个值来替代串中的某个值。 REPLACE ( char, search_string [, replace_string]) 如果没有指定replace_string 变量的值,那么当发现search_string 变量的值时,就将其删除。输入可以为任何字符数据类型——CHAR、VARCHAR2、NCHAR、NVARCHAR2、CLOB或NCLOB。

举例说明

LOWER:大写字符转换为小写字符

/*大写字符转换小写字符*/
SELECT job FROM emp;
SELECT LOWER(job) FROM emp;

UPPER:小写字符转换大写字符

/*小写字符转换为大写字符*/
SELECT class_name FROM stu_class;
SELECT UPPER(class_name) FROM stu_class;

INITCAP:每个单词的第一个字母大写,其它字母变为小写返回. 单词由空格,控制字符,标点符号等非字母符号限制.

/*INITCAP将字符串首字母变为大写,剩余字符小写*/
SELECT INITCAP('mr pmb') FROM dual;

CONCAT:将多个字符串连接成一个字符串

/*CONCAT:将多个字符串连接成一个字符串*/
SELECT CONCAT('a', 'b', 'c') FROM dual;

/*concat连接多个字符时,需要嵌套*/
SELECT CONCAT(CONCAT('a', 'b'), 'c') FROM dual;

SUBSTR:字符截取函数


/*SUBSTR:字符截取函数*/
SELECT * FROM emp ;
/*第一个数字0或者1时候,都是从第一位开始截取*/
SELECT SUBSTR(ename,0,1) FROM emp ;
SELECT SUBSTR(ename,1,1) FROM emp ;
SELECT ename FROM emp;
/*从第一个字符截取后面所有的字符串(0,1结果都是所有字符串)*/
SELECT SUBSTR(ename,0) FROM emp ;
SELECT SUBSTR(ename,1) FROM emp ;
/*从第二个字符截取后面所有的字符串*/
SELECT SUBSTR(ename,2) FROM emp ;

LENGTH:表示字符串长度


/*LENGTH:表示字符串长度*/
SELECT ename,LENGTH(ename) FROM emp;

INSTR:字符查找函数

/*默认第一次出现 'o'的位置 4*/
SELECT INSTR('ello','o') FROM dual ;

/*也就是说:在"helloworld"的第2(e)号位置开始,查找第二次出现的“l”的位*/
/* instr(源字符串, 目标字符串, 起始位置, 匹配序号)*/
SELECT INSTR('helloworld' , 'l',2,2) FROM dual;

LPAD|RPAD:用于往源字符串的左侧填充一些字符

/*LPAD|RPAD:用于往源字符串的左侧填充一些字符*/
/**
 * 'acb':源字符串
 * 10:填充之后的总字符个数
 * 's': 需要填充的字符
 **/
SELECT LPAD('acb',10,'e') FROM dual ;
-- 返回结果 eeeeeeeacb
SELECT RPAD('acb',10,'e') FROM dual ;
-- 返回结果 acbeeeeeee

TRIM:用来去除一个字符串的开头或结尾(或两者)的字符

/*TRIM:用来去除一个字符串的开头或者结尾*/
/*第一种场景:删除空格*/
/*去除字符串前后空格*/
SELECT ' sd abc ',TRIM(' sd abc ') FROM dual;
/*LTRIM去除指定字符的前面空格*/
SELECT ' sd abc ',LTRIM(' sd abc ') FROM dual;
/*RTRIM去除指定字符后面后空格*/
SELECT ' sd abc ',RTRIM(' sd abc ') FROM dual;

/*第二种场景:去除指定的字符。trim只能去除单个字符,而ltrim和rtrim可以去除多个字符*/
/*表示字符串string2去除前面|后面|前后面(leading|trailing|both)的字符string1,默认去除方式为both*/

/*去除字符串 'abnds' 中 'b'(前面)的 字符*/
SELECT TRIM(LEADING 'b' FROM 'abnds') FROM dual;
/*去除字符串 'nnanbndsn' 中 'n'(两侧)的 字符*/
SELECT TRIM(both 'n' FROM 'nnanbndsn') FROM dual;
/*去除字符串 'abnds' 中 's'(后面)的 字符*/
SELECT TRIM(TRAILING 's' FROM 'abnds') FROM dual;

REPLACE:用另外一个值来替代串中的某个值

/*REPLACE:用另外一个值替代串中的某个值*/
SELECT REPLACE('abcdefg','a','0') FROM dual ;
/*返回结果:0bcdefg*/

SELECT REPLACE('abcdefg','a') FROM dual ;
/*返回结果:bcdefg*/

在select使用字符,数字,日期和转换函数

数字函数

语法:ROUND(number[,decimals])
number 待做截取处理的数值
decimals 指明需保留小数点后面的位数。可选项,忽略它则截去所有的小数部分,并四舍五入。如果为负数则表示从小数点开始左边的位数,相应整数数字用0填充,小数被去掉。需要注意的是,和trunc函数不同,对截取的数字要四舍五入。

作用:截取数字 

案例:
/*截取数字:round*/
SELECT ROUND(123.456,3) FROM dual ; -- 123.456
SELECT ROUND(123.456,2) FROM dual ; -- 123.46
SELECT ROUND(123.456,1) FROM dual ; -- 123.5

语法:TRUNC(date,[fmt])  
date 为必要参数,是输入的一个日期值  fmt 参数可忽略,是日期格式,用以指定的元素格式来截去输入的日期值。忽略它则由最近的日期截去
TRUNC(number[,decimals])  其中:  number 待做截取处理的数值  decimals 指明需保留小数点后面的位数。可选项,忽略它则截去所有的小数部分。 
作用:以指定元素格式截去一部分的日期值或者只是该函数不对指定小数前或后的部分做相应舍入选择处理,而统统截去。

案例:
/*以指定元素格式截去一部分的日期值*/
SELECT TRUNC(SYSDATE, 'yyyy') FROM dual; -- 2022/01/01 返回当年第一天
SELECT TRUNC(SYSDATE, 'mm') FROM dual; -- 2022/01/01 返回当月第一天
SELECT TRUNC(SYSDATE, 'd') FROM dual; -- 2022/01/01 返回当周第一天

SELECT TRUNC(12.345, 2) FROM dual; -- 12.34
SELECT TRUNC(12.345) FROM dual; -- 12.3
SELECT TRUNC(12.345,-1) FROM dual; -- 10 此时 小数点左边指定位数后面的部分截去,均以0记
SELECT TRUNC(12.345,-2) FROM dual; -- 0 此时 小数点左边指定位数后面的部分截去,均以0记

语法:mod(m,n)
MOD返回m除以n的余数,如果n是0,返回m,这个函数以任何数字数据类型或任何非数值型数据类型为参数,可以隐式地转换为数字数据类型。

案例:
/*mod:取余*/
SELECT MOD(12, 6) FROM dual; -- 0
SELECT MOD(12, 7) FROM dual; -- 5
SELECT MOD(-12, 7) FROM dual; -- -5

DUAL 是一个‘伪表’,可以用来测试函数和表达式

日期函数

oracle中的日期型数据实际包含两个值:日期和时间

sysdate函数返回 日期+时间
/*获取当前时间*/
SELECT SYSDATE FROM dual; -- 2022/1/13 20:28:21

日期的数学运算
1、日期上加上或者减去一个数字结果仍然是日期
SELECT sysdate,SYSDATE - 1 FROM dual ;   -- 2022/1/13 20:32:09   2022/1/12 20:32:09

2、两个日期之间相减 为相差的天数
注意:日期不允许加法运算
/*两个日期之间相减 为相差的天数*/
SELECT SYSDATE-hiredate FROM emp;

3、可以使用数字除以24来向日期中加上或者减去天数
/*可以使用数字除以24来向日期中加上或者减去天数*/
SELECT SYSDATE+10/24 FROM DUAL ; -- 往后推迟一天

日期函数
months_between
语法:MONTHS_BETWEEN(DATE1,DATE2)
date1:靠前 date2:靠后

作用:两个日期相差的天数

案例:
SELECT  months_between(SYSDATE,hiredate) FROM emp ;
add_months

add_months
语法:add_months(x,y)或者add_months(times,months)函数
这个函数用于计算在时间x之上加上Y个月后的时间值,要是Y的值为负数的话就是在
这个时间点之间的时间值(这个时间-Y个月)

作用:指定日期添加若干月份

案例:
/*指定日期添加若干月份*/
SELECT hiredate, add_months(hiredate, 1) FROM emp; -- 1980/12/17  1981/1/17

next_day
语法:


作用:指定日期的下一个星期*对应的日期

案例:

执行select sysdate from dual;得到当前日期为:2014/4/30 14:11:33  星期三
select  next_day(sysdate,'星期日') from dual;
得到日期为:2014/5/4 14:12:53
从这个礼拜三到得到礼拜天的日期数

last_day

语法:last_day(date)

作用:指定日期对应月份的最后一天

案例:


/*指定日期的最后一天*/
SELECT last_day(SYSDATE) FROM dual; -- 2022/1/31 20:51:55

转换函数

数据类型转换

源数据类型 目标数据类型
VARCHAR2 OR CHAR NUMBER
VARCHAR2 OR CHAR DATE
NUMBER VARCHAR2
DATE VARCHAR2

TO_CHAR函数对日期的转换

TO_CHAR(date,'format_model')

格式:

  • 必须包含在单引号中并且大小写敏感
  • 可以包含任意的有效的日期格式
  • 日期之间使用都好隔开
SELECT TO_CHAR(SYSDATE, 'yyyy-mm-dd hh:mi:ss') FROM dual; -- 2022-01-13 09:03:51

日期格式的元素

YYYY 2000
YEAR TWO THOUSAND
MM 0
MONTH JULY
MON JUL
DY MON
DAY MONDAY
DD 02

日期格式的元素

  • 时间格式
HH24:MI:SS AM 15:45:32 PM
  • 使用双引号向日期中添加字符
DD "OF"< MONTH/td> 12 OF OCTOBER

to_char对日期的转换

SELECT * FROM EMP WHERE TO_CHAR(HIREDATE,'YYYY-MM-DD')='1980-12-17';

TO_DATE对字符的转换

to_date(char,'format_model');

to_date('2022年01月13日21:29:00','yyyy"年"mm"月"dd"日"hh:mi:ss') from dual ;

SELECT to_date('2022年01月13日 1:29:33','yyyy"年"mm"月"dd"日"hh:mi:ss') from dual ;     2022/1/13 1:29:33

TO_DATE对数字的转换

下面是在TO_CHAR 函数中经常使用的几种格式

9 数字
0
$ 美元符
L 本地货币符号
. 小数点
, 千位符
DAY MONDAY
DD 02

案例说明

SELECT to_char(sal, '$99,999.00') FROM emp; --   $1,250.00

通用函数

NVL(exp1,expr2)

nvl2(expr1,expr2,expr3)

nullif(expr1,expr2)

coalesce(expr1,expr2,…)

-- 通用函数
/**
 * NVL:将空值转换成一个已知的值
 * 如果oracle第一个参数为空那么显示第二个参数的值,如果第一个参数的值不为空,则显示第一个参数本来的值。
 * NVL(EXPR1,EXPR2)
 **/
SELECT NVL('第一个参数不为空的值v1','第一个参数空的时候值v2') FROM DUAL;

/**
 * NVL2(EXPR1,EXPR2,EXPR3)
 * 如果该函数的第一个参数为空那么显示第二个参数的值,如果第一个参数的值不为空,则显示第三个参数的值
 **/                 
 SELECT NVL2('',1,2) FROM DUAL; -- 2
 
/**
 * NULLIF(EXPR1,EXPR2)
 * 作用:如果expr1和expr2相等返回null,否则返回第一个值
 **/                                
 SELECT NULLIF(1,2) FROM DUAL;  -- 1   
 
/**
 * COALESCE(EXPR1,V1,...VN)
 * EXPR1:为待检测的表达式,而其后的参数个数不定。
 * 返回值:包括EXPR1在内的所有参数中的第一个非空表达式
 **/                                                          
 
 SELECT COALESCE(NULL,3,4,5) FROM DUAL;

使用条件表达式

  • 在SQL语句中使用IF-THEN-ELSE逻辑
  • 使用两种方法
    • CASE表达式
    • DECODE函数

简单case表达式

-- 简单case表达式
SELECT job,
       CASE JOB
         WHEN 'CLERK' THEN
          'clerk'
         WHEN 'SALESMAN' THEN
          'salesman'
         ELSE
          '其他'
       END
  FROM EMP;

搜索case表达式

-- 搜索case表达式
SELECT JOB, CASE
         WHEN JOB = 'CLERK' THEN
          '职员'
         WHEN JOB = 'SALESMAN' THEN
          '推销员'
         ELSE
          '马会计'
       END
  FROM emp;

注意事项

  • 统一各分支返回的数据类型

虽然这一点无需多言,但这里还是要强调一下:一定要注意 CASE 表达式里各个分支返回的数据类型是否一致。某个分支返回字符型,而其他分支返回数值型的写法是不正确的。

  • 不要忘了写 END

使用 CASE 表达式的时候,最容易出现的语法错误是忘记写 END 。虽然忘记写时程序会返回比较容易理解的错误消息,不算多么致命的错误。但是,感觉自己写得没问题,而执行时却出错的情况大多是由这个原因引起的,所以请一定注意一下。

  • 养成写 ELSE 子句的习惯

与 END 不同,ELSE 子句是可选的,不写也不会出错。不写 ELSE 子句时,CASE 表达式的执行结果是 NULL 。但是不写可能会造成"语法没有错误,结果却不对"这种不易追查原因的麻烦,所以最好明确地写上 ELSE 子句(即便是在结果可以为 NULL 的情况下)。养成这样的习惯后,我们从代码上就可以清楚地看到这种条件下会生成 NULL,而且将来代码有修改时也能减少失误

decode

-- decode函数的两种形式
-- 第一种格式
-- DECODE(EXPR,V1,R1,V2,R2...VN,RN,DEFAULT)
/**
 * IF 条件=V1 THEN R1
 * ELSIF 条件=v2 THEN R2
 * ELSIF 条件=VN THEN RN
 * ELSE RD(缺省值)
 * END IF
 **/
-- 当JOB='CLERK',返回值1 
-- 当JOB='SALESMAN',返回值2
-- 当JOB='MANAGER',返回值3
SELECT EMPNO,
       ENAME,
       JOB,
       DECODE(JOB, 'CLERK', 1, 'SALESMAN', 2, 'MANAGER', 3) NEW_JOB
  FROM EMP;

-- 判断表中sal大小根据大小划分不同范围
SELECT * FROM emp;

SELECT DECODE(SIGN(), 1,) FROM emp;
-- 第二种格式
-- DECODE(字段或者字段运算,V1,V2,V3)
-- 这个函数运行的结果是,当字段或者字段的运算的值等于值1时,该函数返回值2,否则返回值3
-- 当然v1,v2,v3也可以是表达式,这个函数使得SQL语句简单了许多
-- 比较大小
-- SIGN(100-90)表达式值等于-1时候,返回100,否则90
SELECT DECODE(SIGN(100 - 90), -1, 100, 90) FROM DUAL;

-- 使用表达式来搜索字符串
SELECT DECODE(INSTR('ACM', 'C'), 0, '不含有C', '含有C') FROM DUAL; -- 含有C

-- 实现行列转换
-- decode相当于:case when then else end语句
SELECT DECODE(JOB, 'CLERK', ENAME, 0) ENAME_1,
       DECODE(JOB, 'SALESMAN', ENAME, 0) ENAME_2,
       DECODE(JOB, 'MANAGER', ENAME, 0) ENAME_3
  FROM emp;

SELECT * FROM emp;

-- 创建表,插入数据,查询
CREATE TABLE t_decode(id INTEGER, NAME VARCHAR2(10));

-- 插入数据
INSERT INTO t_decode VALUES (1, 'a');
INSERT INTO t_decode VALUES (2, 'b');
INSERT INTO t_decode VALUES (3, 'c');
INSERT INTO t_decode VALUES (4, 'a');

SELECT * FROM T_DECODE;

SELECT decode(NAME, 'a', id, 0) id_1,
       decode(NAME, 'b', id, 0) id_2,
       decode(NAME, 'c', id, 0) id_3
  FROM t_decode;

多表查询

使用等值和不等值连接在SELECT语句中查询多个表中的数据

使用自连接

使用外连接查询不满足连接条件的数据

使用等值和不等值连接在SELECT语句中查询多个表中的数据

从多个表中获取数据

画像-20220115193259679

内连接查询操作列出与连接条件匹配的数据行,它使用比较运算符比较被连接列的列值。

区分重复的列名

  • 使用表名前缀在多个表中区分相同列
  • 不同表中具有相同列名的列可以用表别名加以区分
SELECT * FROM EMP E, DEPT D WHERE EMP.DEPTNO = DEPT.DEPTNO;

画像-20220115194058203

  • 使用别名可以简化查询
  • 使用表名前缀可以提高执行效率

连接多个表

连接n个表,至少需要n-1个连接条件

SELECT S.STU_ID, S.STU_NAME, S1.S_SCORE, SC.CLASS_NAME
  FROM STUDENT S, SCORE S1, STU_CLASS SC
 WHERE S.STU_ID = S1.STU_ID
   AND S1.CLASS_ID = SC.CLASS_ID;

image-20220115201352479

等值连接

等值连接:在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接表中的所有列,包括其中的重复属性。

-- ,形式 and
SELECT S.STU_ID, S.STU_NAME, S1.S_SCORE, SC.CLASS_NAME
  FROM STUDENT S, SCORE S1, STU_CLASS SC
 WHERE S.STU_ID = S1.STU_ID
   AND S1.CLASS_ID = SC.CLASS_ID;
-- INNER JOIN ON   
SELECT S.STU_ID, S.STU_NAME, S1.S_SCORE, SC.CLASS_NAME
  FROM STUDENT S
 INNER JOIN SCORE S1
    ON S.STU_ID = S1.STU_ID
 INNER JOIN STU_CLASS SC
    ON S1.CLASS_ID = SC.CLASS_ID;

image-20220115211726051

非等值连接

不等连接: 在连接条件使用除等于运算符以外的其它比较运算符比较被连接的 列的列值。这些运算符包括>、>=、<=、<、!>、!<和<>。

内连接和外连接

内连接:合并具有同一列的两个以上的表的行,结果集中不包含一个表与另一个表不匹配的行

外连接:两个表在连接过程中除了返回满足连接条件的行之外还需要返回左表或者右表不满足条件的行,这种连接叫做左(右)外连接,没有匹配的行时候,结果表中响应的列为null,外连接的where子句条件类似于内部连接,但是连接条件中没有匹配行的表的列后面需要加上外连接运算符,即 用圆括号括起来的加号。

使用外连接查询不满足连接条件的数据

对应SQL:LEFT/RIGHT/FULL OUTER JOIN。 通常省略OUTER关键字, 写成:LEFT/RIGHT/FULL JOIN。

在左连接和右连接时都会以一张A表为基础表,该表的内容会全部显示,然后加上A表和B表匹配的内容。 如果A表的数据在B表中没有记录。 那么在相关联的结果集行中列显示为空值(NULL)

对于外连接, 也可以使用“(+) ”来表示。 关于使用(+)的一些注意事项

该操作符只能出现在WHERE子句中,并且不能和OURTER JOIN语法同时使用

使用该操作符执行外连接时候,如果WHERE子句包含多个条件,必须在所有条件都包含+操作符

操作符只适用于列,不能用在表达式

操作符不能和OR,IN一起使用

操作符只能用于左外连接和右外连接,不能用于全外连接

左外连接

LEFT JOIN是以左表的记录为基础的,示例中t_A可以看成左表,t_B可以看成右表,它的结果集是t_A表中的全部数据,再加上t_A表和t_B表匹配后的数据。换句话说,左表(t_A)的记录将会全部表示出来,而右表(t_B)只会显示符合搜索条件的记录。t_B表记录不足的地方均为NULL。

语法

-- + 方式
SELECT T1,COLUMN , T2.COLUMN FROM T1,T2 WHERE T1.COLUMN=T2.COLUN(+);

-- LEFT OUTER JOIN 方式
SELECT T1,COLUMN , T2.COLUMN FROM T1 LEFT OUTER JOIN T2 ON T1.COLUMN = T2.COLUMN;

举例说明

-- 返回右表不满足条件的数据
-- 方式1 +
SELECT * FROM STUDENT S1, SCORE S2 WHERE S1.STU_ID = S2.STU_ID(+);

-- 方式2 LEFT OUTER JOIN                      
SELECT *
  FROM STUDENT S1
 LEFT OUTER JOIN SCORE S2
    ON S1.STU_ID = S2.STU_ID;

image-20220115205618225

右外连接

和LEFT JOIN的结果刚好相反,是以右表(SCORE)为基础的。它的结果集是STUDENT表所有记录,再加上SCORE和STUDENT匹配后的数据。STUDENT表记录不足的地方均为NULL。

语法

-- + 方式
SELECT T1,COLUMN , T2.COLUMN FROM T1,T2 WHERE T1.COLUMN(+)=T2.COLUN;

-- LEFT OUTER JOIN 方式
SELECT T1,COLUMN , T2.COLUMN FROM T1 RIGHT OUTER JOIN T2 ON T1.COLUMN = T2.COLUMN;

用(+)来实现, 这个+号可以这样来理解: + 表示补充,即哪个表有加号,这个表就是匹配表。如果加号写在左表,右表就是全部显示,所以是右连接

举例说明

-- 方式1 +
SELECT * FROM STUDENT S1, SCORE S2 WHERE S1.STU_ID(+)= S2.STU_ID;

-- 方式2 RIGHT OUTER JOIN                      
SELECT *
  FROM STUDENT S1
RIGHT OUTER JOIN SCORE S2
    ON S1.STU_ID = S2.STU_ID;

全外连接(FULL OUTER JOIN/FULL JOIN)

完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值

-- FULL JOIN
SELECT * FROM STUDENT S1 FULL JOIN SCORE S2 ON S1.STU_ID = S2.STU_ID; 
-- FULL OUTER JOIN
SELECT * FROM STUDENT S1 FULL OUTER JOIN SCORE S2 ON S1.STU_ID = S2.STU_ID; 

image-20220115210306019

自然连接(NATURAL)

自然连接时在两张表中寻找那些数据类型 和列名都相等的字段,然后自动地将他们连接起来

自然连接,自动匹配同名的列,虽然很方便,不用指定匹配的列

但也有缺点,虽然可以指定查询结果包括哪些列,但不能人为地指定哪些列被匹配,而内连接就可以自由指定

分组函数

通过本次学习,可以知道

  • 了解组函数
  • 描述组函数的用途
  • 使用GROUP BY 子句对数据分组
  • 使用HAVING子句过滤分组结果集

什么是分组函数

分组函数作用于一组数据,并对一组数据返回一个值

组函数类型

AVG 平均值
COUNT 计数
MAX 最大值
MIN 最小值
SUM 求和

AVG()平均值和SUM()求和函数

  • 可以对数值型数据使用SUM和SUM函数
  • AVG组函数忽略空值
SELECT AVG(SAL) FROM EMP;  -- 平均值
SELECT SUM(SAL) FROM EMP;  -- 求和

MIN(最小值)和 MAX(最大值)函数

  • 可以对任意数据类型的数据使用 MIN 和 MAX 函数
-- MAX,MIN
SELECT MAX(SAL)  MAX_VALUE,MIN(SAL) MIN_VALUE FROM EMP;

COUNT(计数)函数

  • 返回记录表中符合条件的记录总数,适用于任意数据类型
  • 使用COUNT(*)对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值
  • 使用COUNT(column)对特定列中具有值的行进行计数,忽略NULL值
-- COUNT(*)
SELECT COUNT(*) FROM EMP WHERE DEPTNO = 20 ;

-- 为空时候
SELECT COUNT(COMM) FROM emp;

image-20220116111824662

组函数与空值

SELECT SUM(COMM),COUNT(*),AVG(COMM) FROM EMP;

原始表中有14条数据,结果看见avg(comm)只对非NULL的数据进行平均操作,那是因为oracle的组函数不会将null的数据进行忽略,如果需要实现对14个人取平均怎么办?

只需要对comm进行nvl操作,将null转换为0,那么组函数就能将这些null数据纳入统计范围了

在组函数中使用NVL函数

  • NVL函数使分组函数无法忽略空值
SELECT SUM(COMM),COUNT(*),AVG(NVL(COMM,0)) FROM EMP;

image-20220116112230637

DISTINCT 关键字

  • COUNT(DISTINCT expr)返回expr非空且不重复的记录总数
SELECT DISTINCT(DEPTNO) FROM EMP;

分组数据: GROUP BY 子句语法

  • 可以使用GROUP BY子句将表中的数据分成若干组
  • 使用聚合函数中用group by来分组数据时特别说明了select 列表项中不存在的列可以出现在group by的列表项中,但反过来就不行了,在select列表项中出现的列必须全部出现在group by后面(聚合函数除外)

WHERE一定放在FROM后面

-- WHERE一定放在FROM后面
SELECT * FROM emp WHERE deptno IN(10,20,30);

在SELECT列表中所有未包含在组函数中的列都应该包含在GROUP BY 子句中

-- 错误示范
SELECT ENAME, DEPTNO FROM EMP GROUP BY DEPTNO;
-- 正确示范
SELECT  DEPTNO ,COUNT(DEPTNO)FROM EMP GROUP BY DEPTNO;

image-20220116113827990

包含在 GROUP BY 子句中的列不必包含在SELECT 列表中

-- 包含在 GROUP BY 子句中的列不必包含在SELECT 列表中
SELECT AVG(sal) FROM emp GROUP BY deptno;

使用多个列分组

-- 多个列分组
SELECT deptno,empno,AVG(sal) FROM emp GROUP BY deptno,empno;

可以在 HAVING 子句中使用组函数

-- 可以在 HAVING 子句中使用组函数
SELECT deptno,AVG(sal) FROM emp HAVING AVG(sal) > 500 GROUP BY deptno;

不能在 WHERE 子句中使用组函数

可以在order by 子句中使用组函数

-- 可以在order by 子句中使用组函数
SELECT deptno, AVG(sal)
  FROM emp
HAVING AVG(sal) > 500
 GROUP BY deptno
 ORDER BY AVG(sal);

非法使用组函数

-- 非法使用组函数
-- 所有包含于SELECT 列表中,而未包含于组函数中的列都必须包含于 GROUP BY 子句中
-- 错误提示:ORA-00937:不是单组分组函数 ,group by 缺少列
SELECT deptno, COUNT(deptno) FROM emp;
-- 不能在 WHERE 子句中使用组函数
-- 错误提示:ORA-00934:此处不允许使用分组函数
SELECT deptno, AVG(sal) FROM emp WHERE AVG(sal) > 500 GROUP BY deptno;
-- 可以在 HAVING 子句中使用组函数
SELECT deptno, AVG(sal)
  FROM emp
HAVING AVG(sal) > 500
 GROUP BY deptno;

过滤分组:HAVING 子句

使用HAVING过滤分组

  • 行已经被分组
  • 使用了组函数
  • 满足HAVING子句条件的分组将被显示
SELECT COLUMN,GROUP_FUNCTION
FROM TABLE
WHERE CONDITION
GROUP BY GROUP_BY_EXPRESSION
HAVING GROUP_CONDITION
ORDER BY COLUMN;

简单使用HAVING

-- 简单使用HAVING
SELECT DEPTNO,AVG(SAL) FROM EMP GROUP BY DEPTNO HAVING MAX(SAL) > 500 ;

嵌套组函数

-- 求出平均工资最高的部门编号,部门名称,部门平均工资
SELECT d.deptno, d.dname, e.sal
  FROM (SELECT AVG(sal) sal, deptno
          FROM emp e
         GROUP BY deptno
        HAVING AVG(sal) = (SELECT MAX(AVG(sal)) FROM emp GROUP BY deptno)) e
  LEFT JOIN dept d
    ON e.deptno = d.deptno;


子查询

目标

  • 描述子查询可以寄解决的问题
  • 定义子查询
  • 列出子查询的类型
  • 书写单行子查询和多行子查询

使用子查询解决的问题

谁的工资比BLAKE高

子查询基本语法

  • 子查询(内查询)在主查询之前一次执行完成
  • 子查询的结果被主查询(外查询)使用
SELECT SELECT_LIST FROM TABLE WHERE EXPR OPERATOR(SELECT SELECT_LIST FROM TABLE)

-- 谁的工资比BLAKE高
SELECT ename,sal
  FROM emp
 WHERE sal >= (SELECT sal FROM emp WHERE ename = 'BLAKE');

注意事项

子查询要包含在括号内

将子查询放在比较条件的右侧

单行操作符对应单行子查询,多行操作符对饮多行子查询

子查询类型

单行子查询:从子查询中返回一行结果的查询

多行子查询:从子查询中返回多行结果的查询

单行子查询

  • 只返回一行
  • 使用单行比较操作符
操作符 含义
= Equal to
> Greater than
>= Greater than or equal to
< Less than
<> 等しくありません
-- 子查询解决的问题
-- 谁的工资比BLAKE高
SELECT * FROM EMP;

-- 子查询的基本语法
SELECT SELECT_LIST
  FROM TABLE
 WHERE EXPR OPERATOR (SELECT SELECT_LIST FROM TABLE);

-- 基本使用
SELECT ENAME, SAL
  FROM EMP
 WHERE SAL >= (SELECT SAL FROM EMP WHERE ENAME = 'BLAKE');

-- 执行单行子查询
-- 返回JOB和7654号员工相同,SAL比7654号员工多的员工姓名,JOB和工资
SELECT ename, job, sal
  FROM emp
 WHERE job = (SELECT job FROM emp WHERE empno = 7369)
   AND sal > (SELECT sal FROM emp WHERE empno = 7369);
-- 子查询中使用组函数
-- 返回公司工资最少的员工的name,job和sal
SELECT ename, job, sal FROM emp WHERE sal = (SELECT MIN(sal) FROM emp);
-- 子查询中使用HAVING
-- 首先执行子查询
-- 向主查询中HAVING子句中返回结果
-- 题目:查询最低工资大于10号部门最低工资的deptno和其最低工资
SELECT deptno, MIN(sal)
  FROM emp
 GROUP BY deptno
HAVING MIN(sal) > (SELECT MIN(sal) FROM emp WHERE deptno = 20);

-- 非法使用子查询
SELECT deptno, ename
  FROM emp
 WHERE sal = (SELECT MIN(sal) FROM emp GROUP BY deptno);
/**
 *  ERROR at line 4:
 * ORA-01427: single-row subquery returns more than
 * one row
 **/

-- 子查询中空值问题
SELECT deptno, MIN(sal)
  FROM emp
 GROUP BY deptno
HAVING MIN(sal) > (SELECT MIN(sal) FROM emp WHERE deptno = 10);

複数行のサブクエリ

  • 複数の行を返す
  • 複数行の比較演算子の使用
オペレーター 意味
リスト内のいずれかと等しい
どれでも サブクエリによって返された値と比較します。
全て サブクエリによって返されたすべての値と比較します
-- 查询工资低于任何一个“CLERK”岗位的工资的雇员信息
SELECT SAL FROM EMP WHERE JOB = 'CLERK';

SELECT MAX(SAL) FROM EMP WHERE JOB = 'CLERK';

SELECT *
  FROM EMP
 WHERE SAL < (SELECT MAX(SAL) FROM EMP WHERE JOB = 'CLERK');

SELECT * FROM EMP;
SELECT *
  FROM EMP
 WHERE SAL < ANY (SELECT SAL FROM EMP WHERE JOB = 'CLERK');

--查询工资比所有的'SALESMAN'职位都高的雇员的编号,名字和工资
--[1]'SALESMAN'工资都是多少?
SELECT SAL FROM EMP WHERE JOB = 'SALESMAN';

SELECT EMPNO, ENAME, SAL
  FROM EMP
 WHERE SAL > ALL (SELECT SAL FROM EMP WHERE JOB = 'SALESMAN');

--查询部门20中的职务同部门10的雇员一样的雇员信息.
--[2]部门10是什么职务
SELECT JOB FROM EMP WHERE DEPTNO = 10;

SELECT *
  FROM EMP
 WHERE JOB IN (SELECT JOB FROM EMP WHERE DEPTNO = 10)
   AND DEPTNO = 20;

テーブルの作成と管理

この章を学習すると、次のことが可能になります。

  • 主要なデータベース オブジェクトを理解する
  • テーブルを作成する
  • さまざまなデータ型を説明する
  • テーブル定義を変更する
  • テーブルを削除、名前変更し、空にする

共通データベースオブジェクト

物体 説明
水面 行と列で構成されるデータ ストアの基本的なコレクション
意見 テーブルから抽出された論理的に関連したデータの集合
順序 通常の値を指定します
索引 クエリ効率の向上
同義語 オブジェクトにエイリアスを付ける

命名規則

テーブル名と列名:

  • 文字で始めなければなりません
  • 1 ~ 30 文字にする必要があります
  • A ~ Z、a ~ z、0 ~ 9、_、$、# のみを含める必要があります
  • 他のユーザー定義オブジェクトと同じ名前を付けることはできません
  • Oracle の予約語であってはなりません

テーブルを作成する

-- 创建表
CREATE TABLE ddept(deptno NUMBER(23), dname VARCHAR2(22), loc VARCHAR2(22));

SELECT * FROM ddept;

データの種類

データの種類 説明
varchar2(サイズ) 可変長文字データ
文字(サイズ) 固定長文字データ
番号 可変長数値データ
日にち 日付型
長さ 可変長文字データ
クロブ キャラクターデータ
バイナリデータ
ROWID 行アドレス

サブクエリを使用してテーブルを作成する

-- 语句:
CREATE TABLE tablename[(column1,column2,column3.....] AS subquery;

例子:

1.create table tabletest as select * from emp where 1=2;

这句话后面的where条件为假,表示只复制表的结构,而不复制数据,当where表后面的条件为真的时候,表示结构和表都复制过去。
2.create table emp20 as select * from emp where deptno=20;
这句话表示会将表的结构以及部门为20号的员工的信息复制过来。

Alter Table ステートメント

  1. 新しい列を追加
  2. 既存の列を変更する
  3. 新しく追加された列のデフォルト値を定義する
  4. 列を削除する
  5. テーブルの列名を変更する

列を変更する

alter table dept modify (last_name varchar2(30));
alter table dept modify (last_name varchar2(30) default '来来来');
-- 对默认值的修改只影响今后对表的修改

追加列

alter table dept add (job_id varchar2(10));

列の削除

alter table dept drop column job_id;

重命名列

alter table dept rename column job_id to id ;

テーブルの削除

  • データと構造の両方が削除されます
  • 実行中の関連トランザクションはすべてコミットされます
  • 関連するすべてのインデックスが削除されます
  • DROP TABLE ステートメントはロールバックできません

要約する

20220124210453

SQLでのif判定の使い方について

大文字と小文字の終わりの構文

SELECT
	CASE
		WHEN math>100 THEN '优'
		WHEN math>90 THEN '良'
		WHEN math>80 THEN '中'
		WHEN math>70 THEN '及格'
		WHEN math IS NULL THEN '缺考'
		ELSE '不及格'
	END
FROM
	Person;

SELECT COUNT(order_num),
       SUM(CASE
             WHEN item_price > 3 THEN
              1
             ELSE
              0
           END)
  FROM orderitems;
/* DECODE方法*/
SELECT COUNT(order_num), SUM(DECODE(1, item_price, 0)) FROM orderitems;

-- 判断字符串
-- 说明:字段empno如果是7014返回1,如果是7015返回2
SELECT empno, ename, COUNT(DECODE(empno, '7014', 1, '7015', 2)) FROM emp;

-- 函数分段
--(负无穷,2)
-- [2,4)
-- [4,+无穷)
SELECT * FROM t_decode;
SELECT ID,
       NAME,
       DECODE(SIGN(ID - 4),
              1,
              'high id',
              0,
              'high id',
              '-1',
              DECODE(SIGN(ID - 2), 1, 'mid id', 0, 'mid id', -1, 'low id'))
  FROM t_decode
   FOR UPDATE;

-- 比较大小
SELECT DECODE(SIGN(100 - 90), -1, 100, 90) FROM dual;

-- 表达式搜索字符串
SELECT ID, NAME, DECODE(INSTR(NAME, 'a'), 0, '不含有a', '含有a')
  FROM t_decode;

-- 行列转换
SELECT DECODE(JOB, 'CLERK', ENAME, 0) ENAME_1,
       DECODE(JOB, 'SALESMAN', ENAME, 0) ENAME_2,
       DECODE(JOB, 'MANAGER', ENAME, 0) ENAME_3
  FROM emp;

おすすめ

転載: blog.csdn.net/greek7777/article/details/126496855