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 Antwort
0
Akzeptierte Antwort

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

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

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

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

Du bist nicht angemeldet. Anmelden um eine Antwort zu veröffentlichen.

Eine gute Antwort beantwortet die Frage klar, gibt konstruktives Feedback und fördert die berufliche Weiterentwicklung des Fragenstellers.

Richtlinien für die Beantwortung von Fragen