postgreSQL その24 SQL INSERT/UPDATE/DELETE文のつづき
postgreSQL その8 課題リストは2018/4/30時点でのオイラの所見
[P.227]
■数値
数値型には下表の種類がある
数値型
|
型名 |
サイズ |
範囲 |
|---|---|---|
|
smallint |
2バイト |
-32768 から +32767 |
|
integer、int |
4バイト |
-2147483648 から +2147483647 |
|
bigint |
8バイト |
-9223372036854775808 から +9223372036854775807 |
|
decimal |
可変長 |
1000桁 |
|
numeric |
可変長 |
1000桁 |
|
real |
4バイト |
6桁の精度 |
|
double |
8バイト |
15桁の精度 |
各データ型について、範囲外の数値を格納しようとするとエラーになる。
可変長のnumericやdecimalは、下記のように精度を指定できる。
testdb=# select * from tb1;
c1 | c2 | c3 | c4
----+-----+----+-----
2 | | | AAA
3 | CCC | | AAA
4 | DDD | | AAA
1 | | | ZZZ
1 | | | ZZZ
(5 rows)
・データ型の範囲
testdb=# update tb1 set c1=2147483647 where c1=1;
UPDATE 2
testdb=# select * from tb1;
c1 | c2 | c3 | c4
------------+-----+----+-----
2 | | | AAA
3 | CCC | | AAA
4 | DDD | | AAA
2147483647 | | | ZZZ ←int型の最大値は格納できる
2147483647 | | | ZZZ ←int型の最大値は格納できる
(5 rows)
testdb=# update tb1 set c1=2147483648 where c1=2;
ERROR: integer out of range ←えら~
testdb=# select * from tb1;
c1 | c2 | c3 | c4
------------+-----+----+-----
2 | | | AAA ←int型の最大値を超える値は格納できない
3 | CCC | | AAA
4 | DDD | | AAA
2147483647 | | | ZZZ
2147483647 | | | ZZZ
(5 rows)
いったんtb1の値をupdate文で下記のように整える
testdb=# select * from tb1;
c1 | c2 | c3 | c4
----+-----+------------+-----
2 | | | AAA
3 | CCC | | AAA
4 | DDD | | AAA
1 | BBB | 2018-05-19 | BBB
5 | EEE | 2018-05-19 | EEE
(5 rows)
・numericやdecimalなどの可変長データ型
numericやdecimalなどは下記のように精度を指定できる。
testdb=# create table tb2 (c1 numeric(3,2)); ←精度3桁、小数点2桁(つまり整数部分は1桁)で指定
CREATE TABLE
testdb=# \d tb2
Table "testschema.tb2"
Column | Type | Collation | Nullable | Default
--------+--------------+-----------+----------+---------
c1 | numeric(3,2) | | |
c1に9.99を代入
testdb=# insert into tb2 values (9.99);
INSERT 0 1 ←格納できた
testdb=# select * from tb2;
c1
------
9.99
(1 row)
c1に9.995を代入
testdb=# insert into tb2 values (9.995);
ERROR: numeric field overflow ←9.995は四捨五入され10になってしまうのでNG
DETAIL: A field with precision 3, scale 2 must round to an absolute value less than 10^1.
testdb=# select * from tb2;
c1
------
9.99
(1 row)
・整数値の指定の仕方
下記は全部OK
testdb=# update tb1 set c1=+10 where c1=1;
UPDATE 1
testdb=# update tb1 set c1='+20' where c1='2';
UPDATE 1
testdb=# update tb1 set c1=-30 where c1='3';
UPDATE 1
testdb=# update tb1 set c2= '-40' where c1= 4;
UPDATE 1
testdb=# update tb1 set c1 ='50' where c1 ='+5';
UPDATE 1
testdb=# update tb1 set c1= '-40' where c1= 4;
UPDATE 1
testdb=# select * from tb1;
c1 | c2 | c3 | c4
-----+-----+------------+-----
10 | BBB | 2018-05-19 | BBB
20 | | | AAA
-30 | CCC | | AAA
50 | EEE | 2018-05-19 | EEE
-40 | -40 | | AAA
(5 rows)
■文字列
文字列を表現する型は、下表のように3種類ある。
文字列型
| 型名 |
説明 |
|---|---|
|
char(n)、character(n) |
空白で埋められた固定長の文字列 |
|
varchar(n)、character varying(n) |
文字数の上限値を指定した可変長の文字列 |
|
text |
可変長の文字列 |
・char型
char型は固定長の文字列を格納する場合に使用する。nには文字数を指定する。
(バイト数ではない)。 nを省略した場合は、char(1)を指定したことになる。nに満たない文字列を格納した場合は、文字の右側が半角の空白文字で埋められる。
たとえば、char(5)で定義した列に「鈴木」を挿入した場合、列には「鈴木△△△」(△は半角スペース)が格納される。 一方、nより大きい文字数を格納しようとするとエラーになる。
ただし、例外的に文字のすべてが半角空白文字だった場合は、nまで切り詰められて格納される。
・varchar型
varchar型は可変長の文字列を格納する場合に使用する。charと同じくnには文字数を指定する。nを省略した場合、上限値無しとして扱われる。nより大きい文字を格納しようとした場合、および文字のすべてが半角の空白文字だった場合の例外処理はchar型と同じ。
・text型
text型は、varchar型と同じく可変長の文字列を格納する場合に使用する。
上限値はなく、varcharのnを省略した場合と同様のふるまいになる。 実際には、text型やnの指定を省略した varchar型は、1GBの文字格納領域が上限となる。
[準備]
testdb=# create table tb3 (c1 char(4),c2 varchar(4),c3 char,c4 varchar,c5 text);
CREATE TABLE
testdb=# \d tb3
Table "testschema.tb3"
Column | Type | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
c1 | character(4) | | |
c2 | character varying(4) | | |
c3 | character(1) | | |
c4 | character varying | | |
c5 | text | | |
・char型
tb3のc1はchar(4)なので、日本語4文字、ASCII4文字、日本語5文字、ASCII5文字を入れてみる
testdb=# insert into tb3(c1) values ('四字熟語'),('a1b2');
INSERT 0 2
testdb=# select * from tb3;
c1 | c2 | c3 | c4 | c5
----------+----+----+----+----
四字熟語 | | | |
a1b2 | | | |
(2 rows)
testdb=# insert into tb3(c1) values ('四文字熟語');
ERROR: value too long for type character(4) ←えら~
testdb=# insert into tb3(c1) values ('a1b2c');
ERROR: value too long for type character(4) ←バイト数に関係なく文字数制限でえら~
testdb=# select * from tb3;
c1 | c2 | c3 | c4 | c5
----------+----+----+----+----
四字熟語 | | | |
a1b2 | | | |
(2 rows)
・変な文字
testdb=# insert into tb3(c1) values ('a1b''); ←4文字目がシングルクォーテーション
testdb'# ;
testdb'# ^C ←「Ctrl」+「c」
testdb=# ←もどった
testdb=# select * from tb3;
c1 | c2 | c3 | c4 | c5
----------+----+----+----+----
四字熟語 | | | |
a1b2 | | | |
(2 rows)
→当然挿入されてない
testdb=# insert into tb3(c1) values ('a1b"'); ←4文字目がダブルクォーテーション
INSERT 0 1
testdb=# select * from tb3;
c1 | c2 | c3 | c4 | c5
----------+----+----+----+----
四字熟語 | | | |
a1b2 | | | |
a1b" | | | | ←ダブルクオーテーションは文字として認識されたんですけど先生
(3 rows)
testdb=# insert into tb3(c1) values ('a1 b'); ←3文字目が全角スペース
INSERT 0 1
testdb=# select * from tb3;
c1 | c2 | c3 | c4 | c5
----------+----+----+----+----
四字熟語 | | | |
a1b2 | | | |
a1b" | | | |
a1 b | | | | ←普通に入った
(4 rows)
下記は全部OKだった
testdb=# insert into tb3(c1) values ('$#]&');
INSERT 0 1
testdb=# insert into tb3(c1) values (')(');
INSERT 0 1
testdb=# insert into tb3(c1) values ('.,^/');
INSERT 0 1
testdb=# select * from tb3;
c1 | c2 | c3 | c4 | c5
----------+----+----+----+----
四字熟語 | | | |
a1b2 | | | |
a1b" | | | |
a1 b | | | |
$#]& | | | |
)( | | | |
.,^/ | | | |
(7 rows)
testdb=# select * from tb3 where c1='.,^/';
c1 | c2 | c3 | c4 | c5
------+----+----+----+----
.,^/ | | | |
(1 row)
→シングルクォーテーション以外はたいてい大丈夫くさい
testdb=# \d tb3
Table "testschema.tb3"
Column | Type | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
c1 | character(4) | | |
c2 | character varying(4) | | |
c3 | character(1) | | | ←「(n)」を省略して定義
c4 | character varying | | |
c5 | text | | |
testdb=# update tb3 set c3='麹' where c1='四字熟語';
UPDATE 1
testdb=# select * from tb3 where c1='四字熟語';
c1 | c2 | c3 | c4 | c5
----------+----+----+----+----
四字熟語 | | 麹 | |
(1 row)
testdb=# update tb3 set c3='麹町' where c1='四字熟語';
ERROR: value too long for type character(1)
testdb=# select * from tb3 where c1='四字熟語';
c1 | c2 | c3 | c4 | c5
----------+----+----+----+----
四字熟語 | | 麹 | |
(1 row)
・varchar型
testdb=# \d tb3
Table "testschema.tb3"
Column | Type | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
c1 | character(4) | | |
c2 | character varying(4) | | | ←これを確認しる
c3 | character(1) | | |
c4 | character varying | | |
c5 | text | | |
testdb=# update tb3 set c2='おまんこ' where c1='四字熟語';
UPDATE 1
testdb=# update tb3 set c2='うんこっこ' where c1='a1b2';
ERROR: value too long for type character varying(4)
testdb=# select * from tb3;
c1 | c2 | c3 | c4 | c5
----------+----------+----+----+----
a1b2 | | | | ←5文字ではえら~
a1b" | | | |
a1 b | | | |
$#]& | | | |
)( | | | |
.,^/ | | | |
四字熟語 | おまんこ | 麹 | | ←4文字なら格納できた
(7 rows)
testdb=# \d tb3
Table "testschema.tb3"
Column | Type | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
c1 | character(4) | | |
c2 | character varying(4) | | |
c3 | character(1) | | |
c4 | character varying | | | ←これを確認しる
c5 | text | | |
testdb=# update tb3 set c4='じゅげむじゅげむ五劫の擦り切れ海砂利水魚のうんぽこぴゅーーーーーーーーー!!!!' where c1='四字熟語';
UPDATE 1
testdb=# select * from tb3 where c1='四字熟語';
c1 | c2 | c3 | c4 | c5
----------+----------+----+------------------------------------------------------------------------+----
四字熟語 | おまんこ | 麹 | じゅげむじゅげむ五劫の擦り切れ海砂利水魚のうんぽこぴゅーーーーーーーーー!!!! |
(1 row)
・text型
testdb=# \d tb3
Table "testschema.tb3"
Column | Type | Collation | Nullable | Default
--------+----------------------+-----------+----------+---------
c1 | character(4) | | |
c2 | character varying(4) | | | ←これを確認しる
c3 | character(1) | | |
c4 | character varying | | |
c5 | text | | | ←これを確認しる
testdb=# update tb3 set c5='隣の竹垣はよく客を食う柿だーーーーーーーーーーー!!!!' where c1='a1b2';
UPDATE 1
testdb=# select * from tb3 where c1='a1b2';
c1 | c2 | c3 | c4 | c5
------+----+----+----+----------------------------------------------------------
a1b2 | | | | 隣の竹垣はよく客を食う柿だーーーーーーーーーーー!!!!
(1 row)
■日付/時刻
日付や時刻などの時間を表現する型は6種類ある。
日付/時刻型
|
型名 |
サイズ |
説明 |
サンプル |
|---|---|---|---|
|
timestamp [without time zone] |
8バイト |
日付と時刻(タイムゾーン無し) |
2017-07-01 12:00:00.000000 |
|
timestamp with time zone |
8バイト |
日付と時刻(タイムゾーンあり) |
2017-07-01 12:00:00.000000+09 |
|
date |
4バイト |
日付(時刻無し) |
2017-07-01 |
|
time [without time zone] |
8バイト |
時刻(タイムゾーン無し) |
12:00:00.000000 |
|
time with time zone |
12バイト |
時刻(タイムゾーンあり) |
12:00:00.000000+09 |
|
interval [fields] |
12バイト |
時間間隔 |
'163 days 18:53:00.21035' |
timeやtimestampで出力される時刻は、マイクロ秒まで表示される。
dateやtimestamp型への入力方法は多岐にわたる。たとえば、2017年7月1日という年月日をdate型として表す場合には、次のような書式を使用できる。
- '2017-07-01'
- '2017/07/01'
- '2017-Jul-01'
- 'Jul 01 2017'
interval型は、時間間隔を表現するやや特殊なデータ型。
「interval '数値 単位'」という形で記述される。 単位は、year、month、day、hour、minuiteなどが使用でき、それらの複数形も受け付ける。
[例]
testdb=# select now();
now
-------------------------------
2018-05-20 01:09:34.650206+09
(1 row)
testdb=# select current_date - interval '1 day';
?column?
---------------------
2018-05-19 00:00:00
(1 row)
testdb=# select current_date - interval '1 hour';
?column?
---------------------
2018-05-19 23:00:00
(1 row)
testdb=# select current_date - interval '0.1 hour';
?column?
---------------------
2018-05-19 23:54:00
(1 row)
■論理値
論理値を表す方は一種類のみ
論理値型
| 型名 |
サイズ |
説明 |
|---|---|---|
|
boolean |
1バイト |
真か偽、もしくは不定(NULL)の状態を保持 |
真偽値の表現には次の文字が使用できる。(大文字と小文字の区別なし)
- 't' 、'f'
- 'true' 、'false'
- 'y' 、'n'
- 'yes' 、'no'
- 'on' 、'off'
- '1'、'0'
- TRUE、FALSE (シングルクォートで囲まない)
※真でも偽でもない状態として、NULLを使用することもできる。
※数値の1と0は、boolean型には使えない
【検証】
testdb=# create table tb4 (c1 boolean);
CREATE TABLE
testdb=# insert into tb4 values ('1');
INSERT 0 1
testdb=# insert into tb4 values ('1'),('False'),('n'),(TRUE),(false),('yes');
INSERT 0 6
testdb=# select * from tb4;
c1
----
t
f
f
t
f
t
(6 rows)
testdb=# insert into tb4 values (0);
ERROR: column "c1" is of type boolean but expression is of type integer
LINE 1: insert into tb4 values (0);
^
HINT: You will need to rewrite or cast the expression.
testdb=# insert into tb4 values (NULL),('on');
INSERT 0 2
testdb=# select * from tb4;
c1
----
t
f
f
t
f
t
f
t
(9 rows)