LoginSignup
27
43

More than 5 years have passed since last update.

【Python】pyodbc経由でSQL Serverにデータを追加する。

Last updated at Posted at 2019-02-11

環境 Windows Python3.7

これからやること

Pythonからpyodbc経由でSQL Serverに接続、SQLでデータを追加する。
前回( https://qiita.com/gaborotta/items/328d01355cd3e12bd070 )取得したデータをSQL Serverに入れておきます。

追加するデータ

テーブルはSQL Serverの方で作成しておく。Pythonからはデータの追加のみ。

  • 動画情報テーブル(動画IDを基にした重複なしテーブルとする)
    • 動画ID
    • 投稿日時
    • 再生時間
    • 過去最高ランク
  • 投稿者情報テーブル(投稿者IDを基にした重複なしテーブルとする)
    • 投稿者ID
    • ユーザー登録時のニコニコ動画のバージョン
    • フォロワー数
    • 投稿動画数
  • 動画-投稿者関連テーブル(動画IDを基にした重複なしテーブルとする)
    • 動画ID
    • 投稿者ID
  • 動画タグテーブル(動画ID and タグ名を基にした重複なしテーブルとする)
    • 動画ID
    • タグ名

pyodbcについて

pythonからODBCを通してデータベースを操作するライブラリ。
SQL構文を介してデータベース側とやりとりが出来る。
詳しくはこちら。
https://docs.microsoft.com/ja-jp/sql/connect/python/pyodbc/python-sql-driver-pyodbc?view=sql-server-2017
https://mkleehammer.github.io/pyodbc/

Windows認証でSQL Serverへ接続

ユーザーIDとパスワードを使って接続もできるけど、こちらの方が楽な気がするので。

    driver='{SQL Server}'
    server = 'localhost\SQLEXPRESS' 
    database = 'データベース名' 
    trusted_connection='yes'

    cnxn = pyodbc.connect('DRIVER='+driver+';SERVER='+server+';DATABASE='+database+';Trusted_Connection='+trusted_connection+';')
    cursor = cnxn.cursor()

接続の切り方

忘れずにcloseしましょう。

    cursor.close()
    cnxn.close()

重複チェックをしてデータの追加

SQLを書いてexecuteで投げる。
commitを忘れずに行わないとデータベースに追加されない。

    sql = "INSERT INTO [dbo].[Hoge]\
        ([ID],[DATE],[DATA])\
        SELECT 1,'20190202','hogehoge'\
        WHERE NOT EXISTS(SELECT [ID] FROM [dbo].[Hoge] WHERE [ID] = '{id}' )"
    cursor.execute(sql)
    cnxn.commit()

実際にやってみた

というわけで、前回取得したデータを全てSQLに突っ込んでみた。

#%%
import pyodbc
import datetime
import json
import sys

###SQL Serverへの接続
def connectSQL():
    driver='{SQL Server}'
    server = 'localhost\SQLEXPRESS' 
    database = 'NicoNico' 
    trusted_connection='yes'

    cnxn = pyodbc.connect('DRIVER='+driver+';SERVER='+server+';DATABASE='+database+';Trusted_Connection='+trusted_connection+';')
    cursor = cnxn.cursor()
    print("ok")
    return cnxn,cursor

def closeSQL(_cursor,_cnxn):
    _cursor.close()
    _cnxn.close()
    print("close")
    return

###Videoデータの追加
def insetVideo(_cn,_cur,_dateStr):
    ##Jsonファイル読み込み
    fr = open("VideoData/"+ _dateStr +".json", 'r',encoding='utf-8')
    videoData = json.load(fr)
    fr.close()

    ##SQLへの書き込み
    #クエリ構文の作成
    SQL_TEMPLATE = "INSERT INTO [dbo].[Video]\
        ([ID],[DATE],[LENGTH],[MAX_RANK],[URL])\
        SELECT '{id}','{date}','{length}','{maxRank}','{videoUrl}'\
        WHERE NOT EXISTS(SELECT [ID] FROM [dbo].[Video] WHERE [ID] = '{id}' )"

    #SQLへの書き込みクエリの実行
    for videoId in videoData:
        editSql = SQL_TEMPLATE                          
        editSql = editSql.replace('{id}', videoId)
        video=videoData[videoId]
        tags=video.pop('tags',None)
        if video["date"] :
            video["date"]=video["date"].replace('年','-').replace('月','-').replace('日','T')
        if video["maxRank"]==sys.maxsize:
            video["maxRank"]=None
        for key,data in video.items():
            editSql = editSql.replace('{' + key + '}', str(data))
        editSql=editSql.replace("None","")
        #print(editSql)
        _cur.execute(editSql)
    #コミット
    _cn.commit()
    return

###Usersデータの追加
def insetUsers(_cn,_cur,_dateStr):
    ##Jsonファイル読み込み
    fr = open("UserData/"+ _dateStr +".json", 'r',encoding='utf-8')
    userData = json.load(fr)
    fr.close()

    ##SQLへの書き込み
    #クエリ構文の作成

    SQL_TEMPLATE = "INSERT INTO [dbo].[Users]\
        ([ID],[NAME],[FOLLOWER_NUM],[VIDEO_NUM],[NICO_VER],[URL])\
        SELECT '{id}','{userName}','{followerNum}','{videoNum}','{nicoVer}','{userUrl}'\
        WHERE NOT EXISTS(SELECT [ID] FROM [dbo].[Users] WHERE [ID] = '{id}' )"

    #SQLへの書き込みクエリの実行
    for userId in userData:
        editSql = SQL_TEMPLATE                          
        editSql = editSql.replace('{id}', userId)
        user=userData[userId]
        for key,data in user.items():
            editSql = editSql.replace('{' + key + '}', str(data))
        editSql=editSql.replace("None","")
        #print(editSql)
        _cur.execute(editSql)
    #コミット
    _cn.commit()
    return

###UsersVideoデータの追加
def insetUsers_Video(_cn,_cur,_dateStr):
    ##Jsonファイル読み込み
    fr = open("User_VideoData/"+ _dateStr +".json", 'r',encoding='utf-8')
    user_videoData = json.load(fr)
    fr.close()

    ##SQLへの書き込み
    #クエリ構文の作成    
    SQL_TEMPLATE = "INSERT INTO [dbo].[UsersVideo]\
        ([VIDEO_ID],[USER_ID])\
        SELECT '{id}','{userId}'\
        WHERE NOT EXISTS(SELECT [VIDEO_ID] FROM [dbo].[UsersVideo] WHERE [VIDEO_ID] = '{id}' )"

    #SQLへの書き込みクエリの実行
    for videoId in user_videoData:
        editSql = SQL_TEMPLATE                          
        editSql = editSql.replace('{id}', videoId)
        editSql = editSql.replace('{userId}', user_videoData[videoId]["userId"])
        editSql=editSql.replace("None","")
        #print(editSql)
        _cur.execute(editSql)
    #コミット
    _cn.commit()
    return

###動画タグデータの追加
def insetVideoTags(_cn,_cur,_dateStr):
    ##Jsonファイル読み込み
    fr = open("VideoData/"+ _dateStr +".json", 'r',encoding='utf-8')
    videoData = json.load(fr)
    fr.close()

    ##SQLへの書き込み
    #クエリ構文の作成
    SQL_TEMPLATE = "INSERT INTO [dbo].[VideoTag]\
        ([VIDEO_ID],[TAG_NAME])\
        SELECT '{id}','{tagName}'\
        WHERE NOT EXISTS(SELECT [VIDEO_ID] FROM [dbo].[VideoTag] WHERE ([VIDEO_ID] = '{id}') AND ([TAG_NAME] LIKE '{tagName}') )"

    #SQLへの書き込みクエリの実行
    for videoId in videoData:
        video=videoData[videoId] 
        if not video["tags"]:   
            continue   
        for tag in video["tags"]:
            name=str(tag).replace("'","''")
            editSql = SQL_TEMPLATE                          
            editSql = editSql.replace('{id}', videoId)
            #print(name)
            editSql = editSql.replace('{tagName}', str(name))
            #print(editSql)
            _cur.execute(editSql)

    #コミット
    _cn.commit()
    return

print("ok")

#%%
##SQL接続
cn,cur=connectSQL()

###データを挿入
date = datetime.date(2019,2,2)
count=365

for num in range(count):
    date -=datetime.timedelta(days=1)
    dateStr=date.strftime("%Y%m%d")
    print(dateStr)
    insetVideo(cn,cur,dateStr)
    insetUsers(cn,cur,dateStr)
    insetUsers_Video(cn,cur,dateStr)
    insetVideoTags(cn,cur,dateStr)

#%%
closeSQL(cn,cur)

結果

前回収集したJsonファイルからデータをSQL Serverに追加できた。
次回はこのデータをRから取り出して統計処理。

27
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
43