現在、S3に格納されているcsvファイルのデータをpythonを使ってRDS(SQL Server)にinsertしてみようと実装を試みています。
下記コードにて、実行してみたところ、csvの一部の列名にて使われている全角記号にてエラーが発生し、SQL Serverにinsertができませんでした。
原因の切り分けとして、insertする列を入れ返してみたところ、全角のカッコ"()"や全角のスラッシュ"/"、全角のアットマーク"@"が入っているとうまくいかないようです。
SQL Serverのテーブルの列には上記の全角の記号を入れているため、列名をそのままにして実装できないかを検討しており、ご教授いただけますと幸いです。
また、pyodbcはlayerに格納しており、pythonは3.11を利用しております。
よろしくお願いいたします。
import pandas as pd #Layerに追加
import csv
import logging
import boto3
import pyodbc #Layerに追加
import sys
import urllib.parse
#rds settings
driver='{ODBC Driver 17 for SQL Server}'
rds_host = "ホスト名"
username = "ユーザー名"
password = "パスワード"
database = "DB名"
logger = logging.getLogger()
logger.setLevel(logging.INFO)
##RDS接続##
connectionString = f'DRIVER={driver};SERVER={rds_host};DATABASE={database};UID={username};PWD={password}'
try:
connect= pyodbc.connect(connectionString)
cursor = connect.cursor()
except:
logger.error("ERROR: Unexpected error: Could not connect to SQL Server instance.")
sys.exit()
##RDS接続成功ログ##
logger.info("SUCCESS: Connection to RDS SQL Server instance succeeded")
def lambda_handler(event, context):
# バケット名,オブジェクト名
BUCKET_NAME = event['Records'][0]['s3']['bucket']['name']
OBJECT_KEY_NAME = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
#S3データ
s3 = boto3.client('s3')
obj = s3.get_object(Bucket=BUCKET_NAME, Key=OBJECT_KEY_NAME)
#readcsv
df = pd.read_csv(obj['Body'])
#SQL Serverにcsvファイルのデータ書き込み
for index, row in df.iterrows():
#データ(@/月) のところを記載するとエラー発生
cursor.execute("INSERT INTO [dbo].[testTable](データA,データB,データ(@/月)) values(?,?,?)", row.データA,row.データB,row.データ(@/月))
connect.commit()
cursor.close()
実行結果
[ERROR] Runtime.UserCodeSyntaxError: Syntax error in module 'test': invalid character '(' (U+FF08) (test.py, line 88) Traceback (most recent call last): File "/var/task/test.py" Line 88 cursor.execute("INSERT INTO [dbo].[testTable](データA,データB,データ(@/月)) values(?,?,?)", row.データA,row.データB,row.データ(@/月))
補足事項:
該当箇所を文字列としてダブルコーテーションを入れた結果を以下に記載いたします。
修正後コードパターン①:前半部分に記載されている「データ(@/月)」をダブルコーテーション
cursor.execute("INSERT INTO [dbo].[testTable](データA,データB,"データ(@/月)") values(?,?,?)", row.データA,row.データB,row.データ(@/月))
実行結果①:
[ERROR] Runtime.UserCodeSyntaxError: Syntax error in module 'test': invalid character '(' (U+FF08) (test.py, line 92) Traceback (most recent call last): File "/var/task/test.py" Line 92 cursor.execute("INSERT INTO [dbo].[testTable](データA,データB,"データ(@/月)") values(?,?,?)", row.データA,row.データB,row.データ(@/月))
修正後コードパターン②:後半部分に記載されている「データ(@/月)」をダブルコーテーション
cursor.execute("INSERT INTO [dbo].[testTable](データA,データB,データ(@/月)) values(?,?,?)", row.データA,row.データB,row."データ(@/月)")
実行結果②:
[ERROR] Runtime.UserCodeSyntaxError: Syntax error in module 'test': invalid syntax (test.py, line 92) Traceback (most recent call last): File "/var/task/test.py" Line 92 cursor.execute("INSERT INTO [dbo].[testTable](データA,データB,データ(@/月)) values(?,?,?)", row.データA,row.データB,row."データ(@/月)")
修正後コードパターン③:前半、後半両方の「データ(@/月)」をダブルコーテーション
cursor.execute("INSERT INTO [dbo].[testTable](データA,データB,"データ(@/月)") values(?,?,?)", row.データA,row.データB,row."データ(@/月)")
実行結果③:
[ERROR] Runtime.UserCodeSyntaxError: Syntax error in module 'test': invalid character '(' (U+FF08) (test.py, line 92) Traceback (most recent call last): File "/var/task/test.py" Line 92 cursor.execute("INSERT INTO [dbo].[testTable](データA,データB,"データ(@/月)") values(?,?,?)", row.データA,row.データB,row."データ(@/月)")
ご回答ありがとうございます。 ご指摘いただいたダブルコーテーションについて実施してみたのですが、うまくいかないのが現状です。 特に、cursor.executeの前半部分に記載されている「データ(@/月)」についてはクエリなのでダブルコーテーションを置く必要がないと思っておりました(同様にエラーが発生)。 前半部分と後半部分それぞれの「データ(@/月)」についてダブルコーテーションを付けて実行してみたところうまくいかなかったため、その内容を質問本文に追記共有させていただきます。
ダブルコーテーションをエスケープしてみるのはどうでしょうか? 例えば以下のような形です。