Webで役立つRDBの使い方

Preview:

Citation preview

Webで役立つRDBの使い方第九回 中国地方DB勉強会 in 米子

What is it?

データベースは何を基準に選んでますか?

What is it?

RDBを制する者は

データ層を制する

と言っても過言ではありません

What is it?今日は

アプリを書く上で便利な事

をご紹介します

What is it?ただし

インデックスやDB設計

の話は今日はしません

What is it?

主にSQLの話です

What is it?

MySQLやPostgreSQLを使う人の

今日から使える便利な知識(SQL)

を持ち帰って活用してください

あじぇんだ

1 自己紹介 2 連番を作る 3 クエリを減らす 4 まとめ

あじぇんだ

1 自己紹介 2 連番を作る 3 クエリを減らす 4 まとめ

自己紹介名前:曽根 壮大(そね たけとも) 年齢:30歳(三人の子供がいます) 職業:Webエンジニア

所属:日本PostgreSQLユーザ会

   中国支部 支部長

  技術的にはLL系言語とかRDBが好きです

あじぇんだ

1 自己紹介 2 連番を作る 3 クエリを減らす 4 まとめ

連番を作る

検索結果に合わせて連番を作る

ID 名前 戦闘力 編

1 フリーザ 530000 フリーザ編

2 悟飯(幼少期) 1307 ラディッツ編

3 クリリン 206 ラディッツ編

4 ヤムチャ 177 ラディッツ編

5 農夫 5 ラディッツ編

6 ギニュー 120000 フリーザ編

7 クリリン 1500 フリーザ編

8 亀仙人 139 ラディッツ編

※実務では編は正規化するべき

連番を作る

MySQLの場合

連番を作る

MySQLの場合 ↓

SQLの中で変数が使える

MySQLの場合SET @num := 0;

SELECT

(@num := @num + 1) AS serial,

キャラクター.*

FROM キャラクター

ORDER BY 戦闘力 DESC;

MySQLの場合SET @num := 0;

SELECT

(@num := @num + 1) AS serial,

キャラクター.*

FROM キャラクター

ORDER BY 戦闘力 DESC;

変数宣言

MySQLの場合SET @num := 0;

SELECT

(@num := @num + 1) AS serial,

キャラクター.*

FROM キャラクター

ORDER BY 戦闘力 DESC;

変数宣言

変数をインクリメントしながら表示

MySQLの場合SELECT

(@num := @num + 1) AS serial,

キャラクター.*

FROM キャラクター,

(SELECT @num := 0 ) AS base

ORDER BY 戦闘力 DESC;

MySQLの場合SELECT

(@num := @num + 1) AS serial,

キャラクター.*

FROM キャラクター,

(SELECT @num := 0 ) AS base

ORDER BY 戦闘力 DESC;

変数宣言をテーブルとして行い、 JOINすることで1回のクエリにする

連番 ID 名前 戦闘力 編

1 1 フリーザ 530000 フリーザ編

2 6 ギニュー 120000 フリーザ編

3 7 クリリン 1500 フリーザ編

4 2 悟飯(幼少期) 1307 ラディッツ編

5 3 クリリン 206 ラディッツ編

6 4 ヤムチャ 177 ラディッツ編

7 8 亀仙人 139 ラディッツ編

8 5 農夫 5 ラディッツ編

※実行結果

連番を作る

他の変数宣言の使い方

MySQLの場合SET sql_mode = 'PIPES_AS_CONCAT';

SET @num := 1;

INSERT INTO users (name)

VALUES (

'soudai+' || (@num := @num + 1)

);

MySQLの場合SET sql_mode = 'PIPES_AS_CONCAT';

SET @num := 1;

INSERT INTO users (name)

VALUES (

'soudai+' || (@num := @num + 1)

);

文字結合を||で出来るようにモード変更

MySQLの場合SET sql_mode = 'PIPES_AS_CONCAT';

SET @num := 1;

INSERT INTO users (name)

VALUES (

'soudai+' || (@num := @num + 1)

);

INSERTを実行するたびに nameが変わる

文字結合を||で出来るようにモード変更

ID 名前 作成日15 soudai+16 "2015-05-30 04:15:24"14 soudai+15 "2015-05-30 04:15:24"13 soudai+14 "2015-05-30 04:15:24"12 soudai+13 "2015-05-30 04:15:24"11 soudai+12 "2015-05-30 04:15:24"10 soudai+11 "2015-05-30 04:15:24"9 soudai+10 "2015-05-30 04:15:24"8 soudai+9 "2015-05-30 04:15:23"7 soudai+8 "2015-05-30 04:15:23"6 soudai+7 "2015-05-30 04:15:23"5 soudai+6 "2015-05-30 04:15:23"4 soudai+5 "2015-05-30 04:15:23"3 soudai+4 "2015-05-30 04:15:23"2 soudai+3 "2015-05-30 04:15:23"1 soudai+2 "2015-05-30 04:15:22"

※実行結果

MySQLの変数宣言その他の使い方

MySQLの変数宣言その他の使い方

1 帳簿などで連続した日付を作る

MySQLの変数宣言その他の使い方

1 帳簿などで連続した日付を作る 2 テストデータの投入

MySQLの変数宣言その他の使い方

1 帳簿などで連続した日付を作る 2 テストデータの投入 3 一時的にデータを保持をする

MySQLの変数宣言その他の使い方

1 帳簿などで連続した日付を作る 2 テストデータの投入 3 一時的にデータを保持をする

MySQLの変数宣言注意点

変数展開は 「いつ実施されるか定まってない」

MySQLの変数宣言注意点

JOINやサブクエリは 先にselect_listが評価される

↓ SELECT @num = @num+1

の+1が行われない

MySQLの変数宣言注意点

JOINやサブクエリは 先にselect_listが評価される

↓ SELECT @num = @num+1

の+1が行われない

対象の列でORDER BYとかしてるとハマる (というかハマった)

連番を作る

PostgreSQLの場合

連番を作る

PostgreSQLの場合 ↓

SQL内での変数宣言が無い

連番を作る

PostgreSQLの場合 ↓

Window関数を使う

連番を作るウィンドウ関数

ウィンドウ関数は現在の行に何らの関係するテーブル行の一纏まり全般の計算を行う。

PostgreSQLの場合SELECT

row_number()

OVER(

ORDER BY 戦闘力 DESC

) AS serial,

*

FROM キャラクター;

PostgreSQLの場合SELECT

row_number()

OVER(

ORDER BY 戦闘力 DESC

) AS serial,

*

FROM キャラクター;

行番号を振る

PostgreSQLの場合SELECT

row_number()

OVER(

ORDER BY 戦闘力 DESC

) AS serial,

*

FROM キャラクター;

行番号を振る

戦闘力で並べる

連番 ID 名前 戦闘力 編

1 1 フリーザ 530000 フリーザ編

2 6 ギニュー 120000 フリーザ編

3 7 クリリン 1500 フリーザ編

4 2 悟飯(幼少期) 1307 ラディッツ編

5 3 クリリン 206 ラディッツ編

6 4 ヤムチャ 177 ラディッツ編

7 8 亀仙人 139 ラディッツ編

8 5 農夫 5 ラディッツ編

※実行結果

連番 ID 名前 戦闘力 編

1 1 フリーザ 530000 フリーザ編

2 6 ギニュー 120000 フリーザ編

3 7 クリリン 1500 フリーザ編

4 2 悟飯(幼少期) 1307 ラディッツ編

5 3 クリリン 206 ラディッツ編

6 4 ヤムチャ 177 ラディッツ編

7 8 亀仙人 139 ラディッツ編

8 5 農夫 5 ラディッツ編

※実行結果

MySQLと同じ結果

連番を作る

区分ごとのランキングも作れる

PostgreSQLの場合SELECT

rank() OVER (

PARTITION BY "編"

ORDER BY "戦闘力" DESC

)

, *

FROM "キャラクター";

PostgreSQLの場合SELECT

rank() OVER (

PARTITION BY "編"

ORDER BY "戦闘力" DESC

)

, *

FROM "キャラクター";

区分を指定する

PostgreSQLの場合SELECT

rank() OVER (

PARTITION BY "編"

ORDER BY "戦闘力" DESC

)

, *

FROM "キャラクター";

区分ごとのランキング

区分を指定する

RANK ID 名前 戦闘力 編

1 2 悟飯(幼少期) 1307 ラディッツ編

2 3 クリリン 206 ラディッツ編

3 4 ヤムチャ 177 ラディッツ編

4 8 亀仙人 139 ラディッツ編

5 5 農夫 5 ラディッツ編

1 1 フリーザ 530000 フリーザ編

2 6 ギニュー 120000 フリーザ編

3 7 クリリン 1500 フリーザ編

※実行結果

RANK ID 名前 戦闘力 編

1 2 悟飯(幼少期) 1307 ラディッツ編

2 3 クリリン 206 ラディッツ編

3 4 ヤムチャ 177 ラディッツ編

4 8 亀仙人 139 ラディッツ編

5 5 農夫 5 ラディッツ編

1 1 フリーザ 530000 フリーザ編

2 6 ギニュー 120000 フリーザ編

3 7 クリリン 1500 フリーザ編

※実行結果

ラディッツ編で集計

フリーザ編で集計

RANK ID 名前 戦闘力 編

1 2 悟飯(幼少期) 1307 ラディッツ編

2 3 クリリン 206 ラディッツ編

3 4 ヤムチャ 177 ラディッツ編

4 8 亀仙人 139 ラディッツ編

5 5 農夫 5 ラディッツ編

1 1 フリーザ 530000 フリーザ編

2 6 ギニュー 120000 フリーザ編

3 7 クリリン 1500 フリーザ編

※実行結果

ラディッツ編で集計

フリーザ編で集計

RANKが別々に振られる

連番を作る

もっと複雑なランキング

名前 戦闘力 編フリーザ 530000 フリーザ編フリーザ 10000000 フリーザ編フリーザ 20000000 フリーザ編

悟飯(幼少期) 1307 ラディッツ編クリリン 206 ラディッツ編ヤムチャ 177 ラディッツ編農夫 5 ラディッツ編ギニュー 120000 フリーザ編クリリン 1500 フリーザ編クリリン 0 フリーザ編クリリン 10000 フリーザ編亀仙人 139 ラディッツ編

ランキングを作る要件

1 戦闘力の降順(DESC) 2 表示はRANKと名前と戦闘力と編 3 編で分ける 4 キャラクターの戦闘力の最大値

実際のSQL

SELECTrank() OVER ( PARTITION BY "編"

ORDER BY max("戦闘力") DESC

) , "名前", MAX("戦闘力"), "編"

FROM "キャラクター2"

GROUP BY "名前","編";

実際のSQL

SELECTrank() OVER ( PARTITION BY "編"

ORDER BY max("戦闘力") DESC

) , "名前", MAX("戦闘力"), "編"

FROM "キャラクター2"

GROUP BY "名前","編"; 集約関数を指定する

実際のSQL

SELECTrank() OVER ( PARTITION BY "編"

ORDER BY max("戦闘力") DESC

) , "名前", MAX("戦闘力"), "編"

FROM "キャラクター2"

GROUP BY "名前","編"; 集約関数を指定する

編ごとの最大戦闘力を指定

RANK 名前 戦闘力 編

1 悟飯(幼少期) 1307 ラディッツ編

2 クリリン 206 ラディッツ編

3 ヤムチャ 177 ラディッツ編

4 亀仙人 139 ラディッツ編

5 農夫 5 ラディッツ編

1 フリーザ 20000000 フリーザ編

2 ギニュー 120000 フリーザ編

3 クリリン 10000 フリーザ編

※実行結果

関数 説明row_number() 行番号rank() ランキング (同率で番号を飛ばす)

dense_rank() ランキング (同率で番号を飛ばさない)

percent_rank() ランキング (%で表示) : (rank - 1) / (全行数 - 1)

cume_dist() percent_rank に類似 : (現在の行の位置) / (全行数)ntile(N) ランキング (1..N に分割)

lag(value, offset, default) ソート状態での前の行の値lead(value, offset, default) ソート状態での後の行の値

first_value(value) 最初の値last_value(value) 最後の値nth_value(value, N) N番目の値 (1から数える)

※Window関数で指定できる関数

連番を作る

PostgreSQLでは 連番を作る関数がある

連番を作る

generate_series(start, end, step)

generate_series()

SELECT

generate_series(1, 10),

generate_series(1, 10, 2),

date(now())

+ generate_series(0, 9)::INT AS day

generate_series()

SELECT

generate_series(1, 10),

generate_series(1, 10, 2),

date(now())

+ generate_series(0, 9)::INT AS day

1から10の連番

generate_series()

SELECT

generate_series(1, 10),

generate_series(1, 10, 2),

date(now())

+ generate_series(0, 9)::INT AS day

1から10の連番

ステップ数を指定した場合

generate_series()

SELECT

generate_series(1, 10),

generate_series(1, 10, 2),

date(now())

+ generate_series(0, 9)::INT AS day

1から10の連番

ステップ数を指定した場合

連続した日付を生成

連番 ステップ指定 日付

1 1 2015-05-30

2 3 2015-05-31

3 5 2015-06-01

4 7 2015-06-02

5 9 2015-06-03

6 1 2015-06-04

7 3 2015-06-05

8 5 2015-06-06

9 7 2015-06-07

10 9 2015-06-08

※実行結果

連番 ステップ指定 日付

1 1 2015-05-30

2 3 2015-05-31

3 5 2015-06-01

4 7 2015-06-02

5 9 2015-06-03

6 1 2015-06-04

7 3 2015-06-05

8 5 2015-06-06

9 7 2015-06-07

10 9 2015-06-08

※実行結果

endの値を超えたので1に戻る

連番を作る

generate_series()を使えば

MySQLのような連番も作れる

あじぇんだ

1 自己紹介 2 連番を作る 3 クエリを減らす 4 まとめ

クエリを減らす

追加と更新を同時にしたい

クエリを減らす

追加と更新を同時にしたい ↓

Merge文

クエリを減らす

残念ながら…

MySQLにもPostgreSQLにも無い

クエリを減らす

MySQLには ↓

ON DUPLICATE KEY UPDATE

クエリを減らすON DUPLICATE KEY UPDATE

プライマリーキー制約やユニーク制約が設定されているカラムにデータを追加する際に、既にデータがあれば例外後にUPDATE文を行う

ON DUPLICATE KEY UPDATE

INSERT users (id, name) SELECT id + 5 AS id, @num := @num + 1 AS name FROM users, (SELECT @num := 0) AS numON DUPLICATE KEY UPDATE name = CONCAT('taketomo', @num := @num + 1)

ON DUPLICATE KEY UPDATE

INSERT users (id, name) SELECT id + 5 AS id, @num := @num + 1 AS name FROM users, (SELECT @num := 0) AS numON DUPLICATE KEY UPDATE name = CONCAT('taketomo', @num := @num + 1)

既存のIDの+5を指定

ON DUPLICATE KEY UPDATE

INSERT users (id, name) SELECT id + 5 AS id, @num := @num + 1 AS name FROM users, (SELECT @num := 0) AS numON DUPLICATE KEY UPDATE name = CONCAT('taketomo', @num := @num + 1)

既存のIDの+5を指定

INSERTの場合

ON DUPLICATE KEY UPDATE

INSERT users (id, name) SELECT id + 5 AS id, @num := @num + 1 AS name FROM users, (SELECT @num := 0) AS numON DUPLICATE KEY UPDATE name = CONCAT('taketomo', @num := @num + 1)

既存のIDの+5を指定

INSERTの場合

UPDATEの場合

ID 名前 作成日

1 soudai+1 "2015-05-30 06:21:50"2 soudai+2 "2015-05-30 06:21:53"3 soudai+3 "2015-05-30 06:21:54"4 soudai+4 "2015-05-30 06:21:55"5 soudai+5 "2015-05-30 06:21:55"6 taketomo10 "2015-05-30 06:21:56"7 taketomo11 "2015-05-30 06:21:58"8 taketomo12 "2015-05-30 06:21:58"9 taketomo13 "2015-05-30 06:21:59"10 5 "2015-05-30 06:22:05"11 6 "2015-05-30 06:22:05"12 7 "2015-05-30 06:22:05"13 8 "2015-05-30 06:22:05"14 9 "2015-05-30 06:22:05"

※実行結果

ID 名前 作成日

1 soudai+1 "2015-05-30 06:21:50"2 soudai+2 "2015-05-30 06:21:53"3 soudai+3 "2015-05-30 06:21:54"4 soudai+4 "2015-05-30 06:21:55"5 soudai+5 "2015-05-30 06:21:55"6 taketomo10 "2015-05-30 06:21:56"7 taketomo11 "2015-05-30 06:21:58"8 taketomo12 "2015-05-30 06:21:58"9 taketomo13 "2015-05-30 06:21:59"10 5 "2015-05-30 06:22:05"11 6 "2015-05-30 06:22:05"12 7 "2015-05-30 06:22:05"13 8 "2015-05-30 06:22:05"14 9 "2015-05-30 06:22:05"

※実行結果

IDが衝突したのでUPADTEした

ID 名前 作成日

1 soudai+1 "2015-05-30 06:21:50"2 soudai+2 "2015-05-30 06:21:53"3 soudai+3 "2015-05-30 06:21:54"4 soudai+4 "2015-05-30 06:21:55"5 soudai+5 "2015-05-30 06:21:55"6 taketomo10 "2015-05-30 06:21:56"7 taketomo11 "2015-05-30 06:21:58"8 taketomo12 "2015-05-30 06:21:58"9 taketomo13 "2015-05-30 06:21:59"10 5 "2015-05-30 06:22:05"11 6 "2015-05-30 06:22:05"12 7 "2015-05-30 06:22:05"13 8 "2015-05-30 06:22:05"14 9 "2015-05-30 06:22:05"

※実行結果

IDが衝突したのでUPADTEした

新規のINSERT

クエリを減らす

MySQLには ↓

REPLACE文

クエリを減らすREPLACE文

プライマリーキー制約やユニーク制約が設定されているカラムで既にデータがあれば対象のデータを削除後にINSERT文を行う

REPLACE

REPLACE users (id, name) SELECT id + 5 AS id, CONCAT('replace', @num := @num + 1) FROM users, (SELECT @num := 0) AS num;

INSERTの条件

既存のIDの+5を指定

ID 名前 作成日1 soudai+1 "2015-05-30 06:21:50"2 soudai+2 "2015-05-30 06:21:53"3 soudai+3 "2015-05-30 06:21:54"4 soudai+4 "2015-05-30 06:21:55"5 soudai+5 "2015-05-30 06:21:55"6 replace1 "2015-05-30 08:06:59"7 replace2 "2015-05-30 08:06:59"8 replace3 "2015-05-30 08:06:59"9 replace4 "2015-05-30 08:06:59"10 replace5 "2015-05-30 08:06:59"11 replace6 "2015-05-30 08:06:59"12 replace7 "2015-05-30 08:06:59"13 replace8 "2015-05-30 08:06:59"14 replace9 "2015-05-30 08:06:59"15 replace10 "2015-05-30 08:06:59"

※実行結果

ID 名前 作成日1 soudai+1 "2015-05-30 06:21:50"2 soudai+2 "2015-05-30 06:21:53"3 soudai+3 "2015-05-30 06:21:54"4 soudai+4 "2015-05-30 06:21:55"5 soudai+5 "2015-05-30 06:21:55"6 replace1 "2015-05-30 08:06:59"7 replace2 "2015-05-30 08:06:59"8 replace3 "2015-05-30 08:06:59"9 replace4 "2015-05-30 08:06:59"10 replace5 "2015-05-30 08:06:59"11 replace6 "2015-05-30 08:06:59"12 replace7 "2015-05-30 08:06:59"13 replace8 "2015-05-30 08:06:59"14 replace9 "2015-05-30 08:06:59"15 replace10 "2015-05-30 08:06:59"

※実行結果

IDがかぶっていないので直接 INSERTしている

ID 名前 作成日1 soudai+1 "2015-05-30 06:21:50"2 soudai+2 "2015-05-30 06:21:53"3 soudai+3 "2015-05-30 06:21:54"4 soudai+4 "2015-05-30 06:21:55"5 soudai+5 "2015-05-30 06:21:55"6 replace1 "2015-05-30 08:06:59"7 replace2 "2015-05-30 08:06:59"8 replace3 "2015-05-30 08:06:59"9 replace4 "2015-05-30 08:06:59"10 replace5 "2015-05-30 08:06:59"11 replace6 "2015-05-30 08:06:59"12 replace7 "2015-05-30 08:06:59"13 replace8 "2015-05-30 08:06:59"14 replace9 "2015-05-30 08:06:59"15 replace10 "2015-05-30 08:06:59"

※実行結果

IDが衝突したのでDELETEして INSERTしている

IDがかぶっていないので直接 INSERTしている

クエリを減らすREPLACE文

• 構文はINSERTと同じ • 対象は全て削除してから作り直す • AUTO_INCREMENTが変わる • 構文でIDを指定しない場合はIDが振り直し

クエリを減らすPostgreSQL 9.5

• INSERTの衝突時のUPDATEが実装される(予定 • ON CONFLICT DO NOTHING/UPDATE • Marge文(UPSERT文)は何年も議論が進んでない (現状の実装ではレアケースでクラッシュするらしい) • Marge文はSQL標準なのでいつか実装する(多分

クエリを減らすPostgreSQL 9.5

• INSERTの衝突時のUPDATEが実装される(予定 • ON CONFLICT DO NOTHING/UPDATE • Marge文(UPSERT文)は何年も議論が進んでない (現状の実装ではレアケースでクラッシュするらしい) • Marge文はSQL標準なのでいつか実装する(多分

クエリを減らす

PostgreSQLにも便利な機能がある↓

RETURNING句

クエリを減らすRETURNING句

PostgreSQLの独自拡張で INSERT・UPDATE・DELETE

の結果を返す

RETURNING

INSERT INTO tmp_log(VALUE)VALUES ('test1') , ('test2') , ('test3')RETURNING *;

RETURNING

INSERT INTO tmp_log(VALUE)VALUES ('test1') , ('test2') , ('test3')RETURNING *;

通常のINSERTの構文

RETURNING

INSERT INTO tmp_log(VALUE)VALUES ('test1') , ('test2') , ('test3')RETURNING *;

通常のINSERTの構文

返す戻り値を指定

ID 名前 作成日

1 test1 "2015-05-30 21:25:18.699022"

2 test2 "2015-05-30 21:25:18.699022"

3 test3 "2015-05-30 21:25:18.699022"

4 test4 "2015-05-30 21:25:18.699022"

5 test5 "2015-05-30 21:25:18.699022"

6 test6 "2015-05-30 21:25:18.699022"

7 test7 "2015-05-30 21:25:18.699022"

※実行結果

RETURNING句使い方

• INSERTしたレコードのIDの確認が不要 • WHERE句を利用したUPDATE文の対象を取得 • WITH句と組み合わせると戻り値を利用できる • WITH句+RETURNING句でMerge文も出来る

WITH+RETURNINGWITH base AS ( SELECT * FROM tmp_log), upd AS ( UPDATE tmp_log SET value = base.value || ' update' FROM base WHERE tmp_log.id > 2 RETURNING tmp_log.id)INSERT INTO tmp_log (value) SELECT value || ‘ INSERT’ FROM base AS ins WHERE id NOT IN (SELECT id FROM upd);

WITH+RETURNINGWITH base AS ( SELECT * FROM tmp_log), upd AS ( UPDATE tmp_log SET value = base.value || ' update' FROM base WHERE tmp_log.id > 2 RETURNING tmp_log.id)INSERT INTO tmp_log (value) SELECT value || ‘INSERT’ FROM base AS ins WHERE id NOT IN (SELECT id FROM upd);

対象のテーブルを指定する

WITH+RETURNINGWITH base AS ( SELECT * FROM tmp_log), upd AS ( UPDATE tmp_log SET value = base.value || ' update' FROM base WHERE tmp_log.id > 2 RETURNING tmp_log.id)INSERT INTO tmp_log (value) SELECT value || ‘INSERT’ FROM base AS ins WHERE id NOT IN (SELECT id FROM upd);

対象のテーブルを指定する

UPDATEを行う

UPDATEしたIDを返す

WITH+RETURNINGWITH base AS ( SELECT * FROM tmp_log), upd AS ( UPDATE tmp_log SET value = base.value || ' update' FROM base WHERE tmp_log.id > 2 RETURNING tmp_log.id)INSERT INTO tmp_log (value) SELECT value || ‘INSERT’ FROM base AS ins WHERE id NOT IN (SELECT id FROM upd);

対象のテーブルを指定する

UPDATEを行う

UPDATEしたIDを返すUPDATE以外の結果を

INSERT

WITH+RETURNING

tmp_log

一時領域

WITH+RETURNING

base tmp_logWITH

一時領域

WITH+RETURNING

base tmp_log

一時領域

upd

UPDATE

WITH+RETURNING

base tmp_log

一時領域

upd

RETURNINGupd

WITH+RETURNING

base tmp_log

一時領域

updupd

ins

ins

サブクエリ

WITH+RETURNING

base tmp_log

一時領域

updupd

ins

ins

INSERT

ins

ID 名前 作成日

1 test1 "2015-05-30 21:41:15.014615"

2 test2 "2015-05-30 21:41:15.014615"

3 test1 update "2015-05-30 21:41:15.014615"

4 test1 update "2015-05-30 21:41:15.014615"

5 test1 update "2015-05-30 21:41:15.014615"

6 test1 update "2015-05-30 21:41:15.014615"

7 test1 update "2015-05-30 21:41:15.014615"

8 test1INSERT "2015-05-30 21:42:32.749261"

9 test2INSERT "2015-05-30 21:42:32.749261"

※実行結果

あじぇんだ

1 自己紹介 2 連番を作る 3 クエリを減らす 4 まとめ

まとめ

まとめ

Webは日々複雑になっている

まとめ

Webは日々複雑になっている ↓

取り扱うデータも増えている

まとめ

運用が始まるとデータは変えれない

まとめ

運用が始まるとデータは変えれない ↓

どんなにコードが綺麗でもデータ構造がダメだとリファクタリングは難しい

まとめ

データの扱い(SQL)を覚える

まとめ

SQLを使ってデータを守る

まとめ

SQLを使ってデータを守る ↓

運用をシンプルにする

まとめ

データの寿命はコードより長い

ご静聴ありがとうございました。