質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

3339閲覧

Python: JSONデータを一括でSQLServerのあるテーブルにINSERTしたい

saya24

総合スコア222

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2020/02/27 01:04

編集2020/03/03 11:31

色々文献をあさっているのですが、こちらの記事を見た限り For文が登場していることから JSONデータのレコードの分 INSERT文を発行しなければならないような作りなのかな?と思いました。

Pythonが稼働する筐体と、DBサーバの筐体は別であり、レコード数に左右してこの筐体間のトラフィックが発生するのは最良ではないような気がしました。

一回のSQL文の発行で、JSONデータを取り込む方法があれば 教えてください。
こちらのMSの記事を見たのですが、今度はDBMS側に特化した記事になっており、Python内で生成されるJSONデータを どうDBMSに適用すれば良いのだろう(ファイルとして保存されていない)、と悩んでいます。

参考になる記事のご紹介でも結構です、ご見解をよろしくお願いします。


14:25追記

Python

1def jsonINSERT(_cn, _cur, jdata): 2 SQL = """ 3 INSERT INTO TSTTBL VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 4 """ 5 _cur.executemany(SQL, jdata) 6 _cn.commit() 7 return

取込もうとしているJSONデータ
JSON

上記executemanyメソッド部分から発せられているだろうエラー

Error

1'The SQL contains 56 parameter markers, but 1 parameters were supplied', 'HY000'

2020/03/03 19:26追記
columns = tuple(fetch_dat[0].keys()) の行で 'str' object has no attribute 'keys' となります...
編集後の実行状況

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yoorwm

2020/02/27 01:25

JSON文字列をそのままINSERTという方法もあるので、そのJSONデータを「どのように使用するのか?」という所を考えて質問すると良いかもしれません。 (ユーザIDだけ拾って、ユーザIDとデータだけのレコードでもいい場合がありますし。)
saya24

2020/02/27 05:24

yoorwmさん SQLServer上のテーブルは 既に業務で運用されているもので、辞書形式の内容は各列に収まる必要があります。現在のステータスを本文に追加します。executemanyメソッドを実行するとエラーが現れています。
guest

回答1

0

ベストアンサー

sqliteでのコード例を示します。ポイントは

  • jsonデータ(に含まれている列名)から動的にSQLクエリ文字列を作成
  • jsonデータからexecutemanyに渡すべき値をタプルにしたリストを作成

です。

Python

1import sqlite3 2import json 3 4# テストテーブルを作成 5con = sqlite3.connect('test.db') 6cur = con.cursor() 7cur.execute('drop table if exists t_test;') 8cur.execute('create table if not exists t_test(num int, str text);') 9cur.executemany("insert into t_test(num, str) values(?,?)",[(1,'a'),(2,'b')]) 10con.commit() 11con.close() 12 13# テストデータ。fetchallなりで取り出してきたもの 14fetch_dat = [('{"num": 3, "str": "c"}',), ('{"num": 4, "str": "d"}',)] 15 16# タプルで包まれているので、包みを取り除く 17fetch_dat = [json.loads(t[0]) for t in fetch_dat] 18print(fetch_dat) # [{'num': 3, 'str': 'c'}, {'num': 4, 'str': 'd'}] 19 20# クエリ文字列を作成 21columns = tuple(fetch_dat[0].keys()) 22params = ['?' for _ in range(len(columns))] 23sql = 'insert into t_test({}) values({})'.format(','.join(columns), ','.join(params)) 24print(sql) # insert into t_test(num,str) values(?,?) 25 26# クエリに渡すデータ。値をタプルにしたリスト 27datas = [tuple(e.values()) for e in fetch_dat] 28 29# テーブルに複数レコード追加 30con = sqlite3.connect('test.db') 31cur = con.cursor() 32cur.executemany("insert into t_test(num, str) values(?,?)",datas) 33con.commit() 34con.close() 35 36# 確認表示 37con = sqlite3.connect('test.db') 38cur = con.cursor() 39cur.execute("select * from t_test;") 40rows = cur.fetchall() 41for row in rows: 42 print( row) 43con.close() 44#(1, 'a') 45#(2, 'b') 46#(3, 'c') 47#(4, 'd')

投稿2020/02/29 02:13

編集2020/03/03 10:50
can110

総合スコア38262

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

saya24

2020/02/29 04:33

can110さん 当方の為に貴重なお時間を頂き有り難うございます。 早速確認して、改めて結果を報告させて頂きます。ちょっと、開発環境の前にいないもので。 まずは御礼まで、また後ほど。
saya24

2020/03/03 06:30

報告が遅れており申し訳ございません、時間が経過してしまっている理由は ご提示を頂きました json_dat = json.loads(XXXX) のステップをうまく自分のコードに適用できずにいるためです。「the JSON object must be str, bytes or bytearray, not 'list」というエラーを招いてしまっています。察するに自分が手配したデータがJSON形式に相応しくないためと思われます。 こちらは res = cur.fetchall()  というように、別データベースから取得したもので、このresを json.loadsの引数に与えている状況です。 ちなみに 変数 res をprint文で確認すると 以下結果を得ています。現在2レコードだけ得るようにしています。 [('{"ITEMCODE":"A001234","DISPLAYREVISIONNO":1,"ITEMNAME":"ABCDEFGHIJKLM","ITEMNAME_ID":"~0000PCJSU"}',), ('{"ITEMCODE":"A002234","DISPLAYREVISIONNO":1,"ITEMNAME":"BCDEFGHIJKLMN","ITEMNAME_ID":"~0000PCPAT"}',)] この 変数resから (' と ',) を除去すれば ご提示されているサンプルのJSONデータに近づけると思うのですが。 すみません、Pythonを始めたばかりで、辞書・タプルの扱いが不慣れで。 差し支えなければ 自分がJSONデータとして認識している ここに示したデータの集団を、どういった関数・加工を施した上で  json.loadsの引数に与えればよいのか 教えてくださいませんか
can110

2020/03/03 09:19

元のデータの形に合わせて回答コードを修正、(' と ',)を取り除くようにしました。
saya24

2020/03/03 09:41

すみません、何から何まで。確認致します。
saya24

2020/03/03 10:34

ご支援をありがとうございます。 columns = tuple(fetch_dat[0].keys()) の部分で 'str' object has no attribute 'keys' というエラーが現われております。まだJSONとして認識されない問題が含まれている、ということでしょうか?? 本文に加工を経たあとのデータの状況、エラー状況を添付致しました、ご確認頂ければ幸いです。
can110

2020/03/03 10:52

よく見たら辞書{~}自体が文字列になっているようですね。コード修正しました。
saya24

2020/03/03 11:26

can110さん、完璧です。この度は至れり尽くせりの対応をありがとうございました。 無事 JSONとして取得したデータベースからのデータを、たった1度のSQL発行で別データベースサーバのテーブルへ データ登録することができました。 頂きましたコード、正直まだよく理解できていないので 今から解読したいと思います。絶対将来にわたっても汎用的に使えるコードに違いありません! 重ねてお礼を申し上げます。
saya24

2020/03/03 22:07 編集

先ほどまで別データベースからJSON形式に格納しているデータは 一先ず2レコードに制限して試していたのですが、この制限を解いたら(WHERE句を外した)、ちょっと困ったことになりました。 cur.executemanyの第二引数に与えるタプルが 1244項目を超えると動作しない様子です。 タプルもしくはリストの限度、ということなのかも知れません。 というと、やはり 何回かにSQL発行を分けるしかない、という結末なのでしょうかね... 一回のSQL発行で、ズドンとJSONデータが所定テーブルの各列に収まることは非常に画期的だと思ったのですが 解決済としながら コメントを書き続けすみません
saya24

2020/03/03 22:35

ご見解をありがとうございます。今は環境が手元になく、発生したエラーメッセージを貼り付けられないのですが、後ほど貼り付けようと思います、すみません。 確かに利用のDBMS•ドライバに依存する部分かも知れませんね。変更設定出来ると良いのですが。 エラーメッセージでググれば 解決できるかな。 ではまた後ほど
saya24

2020/03/04 04:04 編集

fetch_dat = [json.loads(t[0]) for t in fetch_dat] の部分で、 「Expecting value: line 1 column 1244 (char 1243)」 というエラーメッセージが出ていることを確認しました。DBMS云々のはなしではないようでした、妙なことを言ってすみません。 これからググってみますが、現段階で検討がつきません
saya24

2020/03/04 04:03

fetch_dat = [json.loads(t[0]) for t in fetch_dat] のステップで得られるリスト内の辞書ですが、 keyと値の括りをシングルクォートからダブルクォートへ 変更することはできますか? 現在fetch_datのprint結果は [{'ITEMCODE': 'A001234', 'DISPLAYREVISIONNO': 1, 'ITEMNAME': 'ABCDEFGHIJKL', 'ITEMNAME_ID': '~0000PCJSU',.................................... となっています。 http://nekoyukimmm.hatenablog.com/entry/2016/07/14/213140 の記事に その事象を要因に記載されているのですが、別データベースから取得するデータ群の中に意図せずシングルクォートが含まれているのでは?? と疑いだしています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問