psycopg2でUUID型のカラムを含むテーブルにNOT EXISTSを使ってexecute_values関数でバルクインサートしたい

実現したいこと

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

コメントを投稿

0 コメント