開発環境
- macOS Mojave - Apple (OS)
- Emacs (Text Editor)
- Windows 10 Pro (OS)
- Visual Studio Code (Text Editor)
- PostgreSQL (ORDBMS(object-relational database management system))
- Python 3.7 (プログラミング言語)
- psycopg2 (パッケージ)
Head First SQL ―頭とからだで覚えるSQLの基本 (Lynn Beighley (著), 佐藤 直生 (監訳)、松永 多苗子 (翻訳)、オライリージャパン)の4章(賢いテーブル設計 - 正規化の理由)、エクササイズ(p. 189)の解答を求めてみる。
コード
Python 3
#!/usr/bin/env python3
import psycopg2 as sql
conn = sql.connect(database='gregs_list', user='kamimura')
cursor = conn.cursor()
def p(table='your_table'):
_sql = f'select * from {table}'
cursor.execute(_sql)
print(', '.join([column[0] for column in cursor.description]))
for row in cursor.fetchall():
print(row)
print()
_sql = '''drop table if exists your_table'''
cursor.execute(_sql)
conn.commit()
print('1.')
_sql = '''
create table your_table (
id serial primary key,
first_name text,
last_name text
)
'''
print(_sql)
print('2.')
cursor.execute(_sql)
conn.commit()
print('3.')
_sql = '''
insert into your_table values (%s, %s, %s)
'''
values_lisst = [(None, 'マルシア', 'ブレイディ'),
# エラー(シリアルがNone(Null))
(1, 'ジャン', 'ブレイディ'),
(2, 'ボビー', 'ブレイディ'),
(99, 'ピーター', 'ブレイディ')]
for values in values_lisst:
print(values)
try:
cursor.execute(_sql, values)
except Exception as err:
print(type(err), err)
finally:
conn.commit()
p()
_sql = '''
insert into your_table (first_name, last_name) values (%s, %s)
'''
values = ('シンディ', 'プレディ')
try:
print(_sql, values)
cursor.execute(_sql, values)
except Exception as err:
print(err)
finally:
conn.commit()
p()
print('4.')
p()
cursor.close()
conn.close()
入出力結果(Terminal, cmd(コマンドプロンプト), Jupyter(IPython))
$ ./sample2.py
1.
create table your_table (
id serial primary key,
first_name text,
last_name text
)
2.
3.
(None, 'マルシア', 'ブレイディ')
<class 'psycopg2.IntegrityError'> null value in column "id" violates not-null constraint
DETAIL: Failing row contains (null, マルシア, ブレイディ).
id, first_name, last_name
(1, 'ジャン', 'ブレイディ')
id, first_name, last_name
(1, 'ジャン', 'ブレイディ')
(2, 'ボビー', 'ブレイディ')
id, first_name, last_name
(1, 'ジャン', 'ブレイディ')
(2, 'ボビー', 'ブレイディ')
(99, 'ピーター', 'ブレイディ')
id, first_name, last_name
(1, 'ジャン', 'ブレイディ')
(2, 'ボビー', 'ブレイディ')
(99, 'ピーター', 'ブレイディ')
insert into your_table (first_name, last_name) values (%s, %s)
('シンディ', 'プレディ')
duplicate key value violates unique constraint "your_table_pkey"
DETAIL: Key (id)=(1) already exists.
id, first_name, last_name
(1, 'ジャン', 'ブレイディ')
(2, 'ボビー', 'ブレイディ')
(99, 'ピーター', 'ブレイディ')
4.
id, first_name, last_name
(1, 'ジャン', 'ブレイディ')
(2, 'ボビー', 'ブレイディ')
(99, 'ピーター', 'ブレイディ')
$
PostgreSQLにはMySQLのauto incrementがないから代わりにSerialを使って自動で番号を割り当てようとしたけど、最初は1番から割り当てていくみたいで、既に割り当てられてる1を割り当てようとして、プライマリーキーの重複でエラーになるみたい。
idの1番は開けておいてから自動で割り当ててみる。
コード
Python 3
#!/usr/bin/env python3
import psycopg2 as sql
conn = sql.connect(database='gregs_list', user='kamimura')
cursor = conn.cursor()
def p(table='your_table'):
_sql = f'select * from {table}'
cursor.execute(_sql)
print(', '.join([column[0] for column in cursor.description]))
for row in cursor.fetchall():
print(row)
print()
_sql = '''drop table if exists your_table'''
cursor.execute(_sql)
conn.commit()
print('1.')
_sql = '''
create table your_table (
id serial primary key,
first_name text,
last_name text
)
'''
print(_sql)
print('2.')
cursor.execute(_sql)
conn.commit()
print('3.')
_sql = '''
insert into your_table values (%s, %s, %s)
'''
values_lisst = [(None, 'マルシア', 'ブレイディ'),
# エラー(シリアルがNone(Null))
(2, 'ジャン', 'ブレイディ'),
(3, 'ボビー', 'ブレイディ'),
(99, 'ピーター', 'ブレイディ')]
for values in values_lisst:
print(values)
try:
cursor.execute(_sql, values)
except Exception as err:
print(type(err), err)
finally:
conn.commit()
p()
_sql = '''
insert into your_table (first_name, last_name) values (%s, %s)
'''
values = ('シンディ', 'プレディ')
try:
print(_sql, values)
cursor.execute(_sql, values)
except Exception as err:
print(err)
finally:
conn.commit()
p()
print('4.')
p()
cursor.close()
conn.close()
入出力結果(Terminal, cmd(コマンドプロンプト), Jupyter(IPython))
$ ./sample2.py
1.
create table your_table (
id serial primary key,
first_name text,
last_name text
)
2.
3.
(None, 'マルシア', 'ブレイディ')
<class 'psycopg2.IntegrityError'> null value in column "id" violates not-null constraint
DETAIL: Failing row contains (null, マルシア, ブレイディ).
id, first_name, last_name
(2, 'ジャン', 'ブレイディ')
id, first_name, last_name
(2, 'ジャン', 'ブレイディ')
(3, 'ボビー', 'ブレイディ')
id, first_name, last_name
(2, 'ジャン', 'ブレイディ')
(3, 'ボビー', 'ブレイディ')
(99, 'ピーター', 'ブレイディ')
id, first_name, last_name
(2, 'ジャン', 'ブレイディ')
(3, 'ボビー', 'ブレイディ')
(99, 'ピーター', 'ブレイディ')
insert into your_table (first_name, last_name) values (%s, %s)
('シンディ', 'プレディ')
id, first_name, last_name
(2, 'ジャン', 'ブレイディ')
(3, 'ボビー', 'ブレイディ')
(99, 'ピーター', 'ブレイディ')
(1, 'シンディ', 'プレディ')
4.
id, first_name, last_name
(2, 'ジャン', 'ブレイディ')
(3, 'ボビー', 'ブレイディ')
(99, 'ピーター', 'ブレイディ')
(1, 'シンディ', 'プレディ')
$
うまくいった。serial型のidに1を割り当てた後どうなるかも確認してみる。
コード
Python 3
#!/usr/bin/env python3
import psycopg2 as sql
conn = sql.connect(database='gregs_list', user='kamimura')
cursor = conn.cursor()
def p(table='your_table'):
_sql = f'select * from {table}'
cursor.execute(_sql)
print(', '.join([column[0] for column in cursor.description]))
for row in cursor.fetchall():
print(row)
print()
_sql = '''drop table if exists your_table'''
cursor.execute(_sql)
conn.commit()
print('1.')
_sql = '''
create table your_table (
id serial primary key,
first_name text,
last_name text
)
'''
print(_sql)
print('2.')
cursor.execute(_sql)
conn.commit()
print('3.')
_sql = '''
insert into your_table values (%s, %s, %s)
'''
values_lisst = [(None, 'マルシア', 'ブレイディ'),
# エラー(シリアルがNone(Null))
(2, 'ジャン', 'ブレイディ'),
(3, 'ボビー', 'ブレイディ'),
(99, 'ピーター', 'ブレイディ')]
for values in values_lisst:
print(values)
try:
cursor.execute(_sql, values)
except Exception as err:
print(type(err), err)
finally:
conn.commit()
p()
_sql = '''
insert into your_table (first_name, last_name) values (%s, %s)
'''
values = ('シンディ', 'プレディ')
for _ in range(2):
try:
print(_sql, values)
cursor.execute(_sql, values)
except Exception as err:
print(err)
finally:
conn.commit()
p()
print('4.')
p()
cursor.close()
conn.close()
入出力結果(Terminal, cmd(コマンドプロンプト), Jupyter(IPython))
$ ./sample2.py
1.
create table your_table (
id serial primary key,
first_name text,
last_name text
)
2.
3.
(None, 'マルシア', 'ブレイディ')
<class 'psycopg2.IntegrityError'> null value in column "id" violates not-null constraint
DETAIL: Failing row contains (null, マルシア, ブレイディ).
id, first_name, last_name
(2, 'ジャン', 'ブレイディ')
id, first_name, last_name
(2, 'ジャン', 'ブレイディ')
(3, 'ボビー', 'ブレイディ')
id, first_name, last_name
(2, 'ジャン', 'ブレイディ')
(3, 'ボビー', 'ブレイディ')
(99, 'ピーター', 'ブレイディ')
id, first_name, last_name
(2, 'ジャン', 'ブレイディ')
(3, 'ボビー', 'ブレイディ')
(99, 'ピーター', 'ブレイディ')
insert into your_table (first_name, last_name) values (%s, %s)
('シンディ', 'プレディ')
id, first_name, last_name
(2, 'ジャン', 'ブレイディ')
(3, 'ボビー', 'ブレイディ')
(99, 'ピーター', 'ブレイディ')
(1, 'シンディ', 'プレディ')
insert into your_table (first_name, last_name) values (%s, %s)
('シンディ', 'プレディ')
duplicate key value violates unique constraint "your_table_pkey"
DETAIL: Key (id)=(2) already exists.
id, first_name, last_name
(2, 'ジャン', 'ブレイディ')
(3, 'ボビー', 'ブレイディ')
(99, 'ピーター', 'ブレイディ')
(1, 'シンディ', 'プレディ')
4.
id, first_name, last_name
(2, 'ジャン', 'ブレイディ')
(3, 'ボビー', 'ブレイディ')
(99, 'ピーター', 'ブレイディ')
(1, 'シンディ', 'プレディ')
$
serialは自動では1の次に2と順番に割り当てていくみたいで、既にテーブルに存在する番号の確認は行わないみたい。(もしかしたら何か制御する方法はあるのかも)
ということで、(制御する方法がないなら)serial型は全て自動で割り当てるようにした方が良さそう。
0 コメント:
コメントを投稿