SQL
DML:Data Manipulation Language
DDL:Data Definition Language
DCL:Data Control Language
Oracle:テーブルDDL
CREATE TABLE MEMBER(
ID CHAR(8) PRIMARY KEY,
NAME CHAR(30) DEFAULT '仮名' NOT NULL,
AGE NUMBER(3) DEFAULT 0 NOT NULL,
REGISTER_DATE DATE DEFAULT SYSDATE NOT NULL,
DETAIL_ID CHAR(5) DEFAULT '99999' NOT NULL,
CONSTRAINT FK_XXX FOREIGH_KEY (DETAIL_ID)
REFERENCES MEMBER_DETAIL (DETAIL_ID)
)
★基本(SQL Server)
●SELECT文
SELECT DISTINCT name FROM table;
SELECT TOP 3 * FROM table ORDER BY NEWID(); --ランダムに取得
SELECT * FROM table ORDER BY RAND() LIMIT 3; --MySQL
SELECT COUNT(*) FROM table;
SELECT COUNT(name) FROM table; --NULLではない行
SELECT COUNT(DISTINCT name) FROM table;
SELECT t.id as 番号, t.name '名前' FROM table t;
SELECT (age + id) col FROM table;
SELECT t1.name + '-' t2.name FROM table1 t1, table2 t2 WHERE t1.id = t2.cid;
SELECT * FROM table WHERE id <> 3;
SELECT * FROM table WHERE id <= 3 AND sex = 1;
SELECT * FROM table WHERE id NOT BETWEEN 2 AND 5;
SELECT * FROM table WHERE name NOT LIKE '%[j,n]%';
SELECT * FROM table WHERE id NOT IN (2, 3);
SELECT * FROM table WHERE age IS NOT NULL;
SELECT * FROM table ORDER BY name ASC/DESC;
SELECT COUNT(age), age FROM table WHERE id > 2 GROUP BY age;
SELECT COUNT(*), set FROM table GROUP BY sex, age ORDER BY age;
SELECT COUNT(*), age FROM table GROUP BY age HAVING COUNT(age) >= 3 AND MAX(id) > 2;
SELECT
CASE WHEN LEN(news_content) > 10
THEN LEFT(news_content, 10) + '...'
ELSE news_content
END news_name,
news_id
FROM table
⇒内部クエリ
SELECT *, (SELECT COUNT(*) FROM table1 WHERE cid = table2.id) num
FROM table2 ORDER BY num;
SELECT * FROM table1 WHERE cid in (
SELECT id FROM table2 WHERE id > 5
);
SELECT t1.title, t2.updateDate
FROM table t1, (SELECT MAX(updateDate) updateDate FROM table2 WHERE table2.title = t1.title) t2;
SELECT t1.title, t1.updateDate FROM tabl1 t1
WHERE updateDate = (SELECT MAX(updateDate) FROM table2 t2 WHERE t2.name = t1.name)
WHERE句副クエリ
SELECT order_id, custom_id
FROM order
WHERE custom_id EXISTS
(SELECT custom_id FROM customer WHERE custom_name='Andy');
FROM句副クエリ
SELECT o.order_id, o.custom_id
FROM
order o,
(SELECT custom_id FROM customer WHERE custom_name='Andy') c
WHERE o.custom_id = c.custom.id;
⇒ソート関連
--連番
SELECT t1.id, t1.name, t2.id, t2.name, ROW_NUMBER() OVER(ORDER BY t2.name) num
FROM table1 t1, table2 t2 WHERE t1.cid = t2.id;
※RANK()、DENSE_RANK()
--部分に分ける
SELECT t1.id, t1.name, t2.id, t2.name, NTILE(3) OVER(ORDER BY t2.name) num
FROM table1 t1, table2 t2 WHERE t1.cid = t2.id;
⇒集合の演算
--結合
SELECT id, name FROM table WHERE name like 'an%';
UNION
SELECT id, name FROM table WHERE id = 3;
※UNION 重複なし
※UNION ALL 重複あり、速い
--同じ部分
SELECT id, name FROM table WHERE name like 'an%';
INTERSECT
SELECT id, name FROM table WHERE id = 3;
--違う部分
SELECT id, name FROM table WHERE name like 'an%';
EXCEPT
SELECT id, name FROM table WHERE id = 3;
⇒JOIN
SELECT t1.id, t1.name, t2.id, t2.name FROM table1 t1, table2 t2 WHERE t1.cid = t2.id;
SELECT t1.id, t1.name, t2.id, t2.name FROM table1 t1 LEFT/RIGHT/INNER JOIN table2 t2 ON t1.cid = t2.id;
--同じテーブル
SELECT DISTINCT t1.* FROM table t1, table t2 WHERE t1.id <> t2.id AND t1.set = t2.set;
●SELECT文以外
UPDATE table SET name = 'Andy', sex = 2 WHERE id = 5;
UPDATE
table1
SET
updateDate = GETDATE()
,bitFlg ^= 4
,version += 1
FROM
table1 t1
LEFT JOIN table2 t2
ON t1.id = t2.id
WHERE
t1.bitFlg & 1 = 1;
INSERT INTO table(id, name, set) VALUES(10, 'Andy', 2);
INSERT INTO table1
SELECT t2.id, t2.name, t2.sex FROM table2 WHERE id > 9;
DELETE FROM table1 t1 WHERE NOT EXISTS(
SELECT * FROM table2 WHERE t1.cid = t2.id
);
★NULLについて
SELECT * FROM TableA A
WHERE A.ID NOT IN (SELECT ID FROM TableB) ←TableB.IDがNULLの場合を考慮してない
対策1
SELECT * FROM TableA A
WHERE A.ID NOT IN (SELECT ID FROM TableB WHERE ID IS NOT NULL)
対策2(推薦)
SELECT * FROM TableA A
WHERE NOT EXISTS (SELECT * FROM TableB B WHERE B.ID = A.ID)
NULLと算術式
SELECT ID, NVL(COST, 0) AS COST FROM TableC
★SQL文のエスケープ
対策:WildCardを無効にする
LIKE条件の場合
% 任意の文字列
_ 任意の1文字
SELECT * FROM TableA WHERE NAME LIKE '%_%'; ×
SELECT * FROM TableA WHERE NAME LIKE '%¥_%' ESCAPE '¥'; 〇
Java+Oracleサンプル
public String method(String query){
if(query != null && query.length() > 0){
String escaped = query.replace("'", "''") // 特殊文字
.replace("@", "@@") // エスケープ
.replace("%", "@%") // 半角
.replace("_", "@_") // 半角
.replace("%", "@%") // 全角
.replace("_", "@_"); // 全角
return String.format("SELECT * FROM TableA WHERE DEL_FLG='0' AND NAME LIKE '%%s%' ESCAPE '@'", escaped);
}
return null;
}
★制約(Oracle)
・NOT NULL NN_テーブル名_カラム名
・UNIQUE UK_テーブル名_カラム名
・PRIMARY KEY PK_テーブル名
・FOREIGN KEY FK_テーブル名_カラム名
・CHECK CK_テーブル名_カラム名
・REF DF_テーブル名_カラム名
★ソートについて
ソート処理が重いので、避けるべき
下記のSQL文ではソート処理が行うかもしれない
ORDER BY
GROUP BY
DISTINCT
EXISTS / NOT EXISTS
IN / NOT IN
UNION(UNION ALLではソート処理なしが、重複データを除かない)
MINUS
INTERSECT
CREATE INDEX
MERGE JOIN
★日付について
Oracleの場合
SELECT * FROM Table A
WHERE A.UPDATE_DATE >= TO_DATE('2012-04-11', 'YYYY-MM-DD') ←時分秒を考慮せず
AND A.UPDATE_DATE <= TO_DATE('2012-04-11', 'YYYY-MM-DD');
対策1 × Indexが利用できない
SELECT * FROM Table A
WHERE TO_CHAR(A.UPDATE_DATE, 'YYYY-MM-DD') >= '2012-04-11'
AND TO_CHAR(A.UPDATE_DATE, 'YYYY-MM-DD') <= '2012-04-11';
対策2 〇
SELECT * FROM Table A
WHERE A.UPDATE_DATE >= TO_DATE('2012-04-11 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND A.UPDATE_DATE <= TO_DATE('2012-04-11 23:59:59', 'YYYY-MM-DD HH24:MI:SS');
★SQL注意点
・WHERE文には、選択率の低い順から書く
・IN文には、選択率の高い順から書く
※他サイトを参照