実現したいこと
postgresqlのテーブルでUUID型のカラムを含むテーブルにバルクインサートしたいです。
NOT EXISTS句でチェックをしてインサートをしたいのですが、NOT EXISTS句を含めるとエラーが出てうまくいきません。
前提
テーブル定義
SQL
1\c postgres 2 3CREATE SCHEMA TEST; 4 5CREATE TABLE TEST.USER ( 6 id UUID, 7 name VARCHAR(100) 8);
発生している問題・エラーメッセージ
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-24-01916b6c2dc7> in <module> 18 with get_connection() as conn: 19 with conn.cursor() as cur: ---> 20 extras.execute_values(cur, sql, params) ~/python_env/ml/lib/python3.7/site-packages/psycopg2/extras.py in execute_values(cur, sql, argslist, template, page_size, fetch) 1294 parts = pre[:] 1295 for args in page: -> 1296 parts.append(cur.mogrify(template, args)) 1297 parts.append(b',') 1298 parts[-1:] = post ValueError: only bytes values expected, got NoneType
該当のソースコード
python
1import psycopg2 2import uuid 3from psycopg2 import extras 4from psycopg2.extensions import ISQLQuote 5 6# DB接続情報 7DB_HOST = 'localhost' 8DB_PORT = '5432' 9DB_NAME = 'postgres' 10DB_USER = 'postgres' 11DB_PASS = 'password' 12SCHEMA = "TEST" 13 14def get_connection(): 15 return psycopg2.connect( 16 f"postgresql://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}" 17 ) 18 19psycopg2.extensions.register_adapter(uuid.UUID, ISQLQuote) 20sql = f""" 21 INSERT INTO {SCHEMA}.USER 22 SELECT v.id, v.name 23 FROM (VALUES %s) AS v(id, name) 24 WHERE NOT EXISTS ( 25 SELECT 1 FROM {SCHEMA}.USER WHERE name = v.name 26 ); 27 """ 28params = [ 29 (uuid.uuid4(), 'test1'), 30 (uuid.uuid4(), "test2") 31] 32with get_connection() as conn: 33 with conn.cursor() as cur: 34 extras.execute_values(cur, sql, params)
試したこと
上記ソースコードのsql, params変数の箇所を下記のように修正すると正常にインサートされます。
python
1# sqlはNOT EXISTSを使わない形 2sql = f""" 3 INSERT INTO {SCHEMA}.USER 4 VALUES %s; 5 """ 6# paramsはUUID型から文字列型に変更 7params = [ 8 (str(uuid.uuid4()), 'test1'), 9 (str(uuid.uuid4()), ’test2’) 10]
下記のようなNOT EXISTSを使うSQLだと、
python
1sql = f""" 2 INSERT INTO {SCHEMA}.USER 3 SELECT v.id, v.name 4 FROM (VALUES %s) AS v(id, name) 5 WHERE NOT EXISTS ( 6 SELECT 1 FROM {SCHEMA}.USER WHERE name = v.name 7 ); 8 """
下記のようなエラーになります。
--------------------------------------------------------------------------- DatatypeMismatch Traceback (most recent call last) <ipython-input-26-a21cf7e66973> in <module> 19 with get_connection() as conn: 20 with conn.cursor() as cur: ---> 21 extras.execute_values(cur, sql1, params) ~/python_env/ml/lib/python3.7/site-packages/psycopg2/extras.py in execute_values(cur, sql, argslist, template, page_size, fetch) 1297 parts.append(b',') 1298 parts[-1:] = post -> 1299 cur.execute(b''.join(parts)) 1300 if fetch: 1301 result.extend(cur.fetchall()) DatatypeMismatch: column "id" is of type uuid but expression is of type text LINE 3: SELECT v.id, v.name ^ HINT: You will need to rewrite or cast the expression.
補足情報(FW/ツールのバージョンなど)
環境はDockerを使用しcomposeファイルは下記になります。
docker
1volumes: 2 testdb: 3 external: false 4 name: testdb 5 6services: 7 postgres: 8 container_name: testdb 9 image: postgres:15.3 10 volumes: 11 - testdb:/var/lib/postgresql/data 12 - ./script:/docker-entrypoint-initdb.d 13 ports: 14 - "5432:5432" 15 environment: 16 TZ: Asia/Tokyo 17 POSTGRES_DB: postgres 18 POSTGRES_USER: postgres 19 POSTGRES_PASSWORD: password 20 POSTGRES_ROOT_PASSWORD: root 21 POSTGRES_INITDB_ARGS: "--encoding=UTF-8" 22 hostname: postgres 23 restart: always 24

回答1件
あなたの回答
tips
プレビュー