S3格納のcsvファイルからRDS(SQL Server)に対して全角文字の列名が含まれるデータのinsert方法(Labmda、Python、pyodbc)

0

現在、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."データ(@/月)")

1回答
0
承認された回答

「(@/月)」が問題であればダブルクォーテーションなどで囲って文字列として扱ってみるのはどうでしょうか?
例えば以下のようにするとどうでしょうか?

cursor.execute("INSERT INTO [dbo].[testTable](データA,データB,"データ(@/月)") values(?,?,?)", row.データA,row.データB,row.データ(@/月))
profile picture
エキスパート
回答済み 4ヶ月前
  • ご回答ありがとうございます。 ご指摘いただいたダブルコーテーションについて実施してみたのですが、うまくいかないのが現状です。 特に、cursor.executeの前半部分に記載されている「データ(@/月)」についてはクエリなのでダブルコーテーションを置く必要がないと思っておりました(同様にエラーが発生)。 前半部分と後半部分それぞれの「データ(@/月)」についてダブルコーテーションを付けて実行してみたところうまくいかなかったため、その内容を質問本文に追記共有させていただきます。

  • ダブルコーテーションをエスケープしてみるのはどうでしょうか? 例えば以下のような形です。

    cursor.execute("INSERT INTO [dbo].[testTable](データA,データB,\"データ(@/月)\") values(?,?,?)", row.データA,row.データB,row.データ(@/月))
    

ログインしていません。 ログイン 回答を投稿する。

優れた回答とは、質問に明確に答え、建設的なフィードバックを提供し、質問者の専門分野におけるスキルの向上を促すものです。

質問に答えるためのガイドライン