mysql」カテゴリーアーカイブ

mysqlの説明

MySqlでDB、テーブル作成メモ 備忘録

MySqlでDB、テーブル作成メモ(条件はユーザはすでに作成済)
株式市場の企業の株価と出来高を登録する。
pythonを使ったスクレイピング処理をこれから行う。この記事にはPythonの記載はない。
mysqldbを使用していたがmysql-connector-pythonが良いらしいのでpip install済

ターミナルでの作業

最近忘れっぽくて、使っていないコマンドをどんどん忘れている。SQL文も忘れてるので、備忘録メモとして記載しておく。記憶力の低下に抵抗せずに、メモをしていつでも思い出せるかメモを見ながら作業するようにする。

・ユーザはmaseda
mysql -u maseda -p
psssはTes*****にした。上に記載。このパスワードはデモ用なので知られてOK

・DBを作成
CREATE DATABASE YahooFinance DEFAULT CHARACTER SET utf8mb4;

・DBを指定する
use YahooFinance;

重複を避けるときはUNIQUEを使う
UNIQUE uni_Code int(5) NOT NULL,
>>今回は使用せず
mysqlのコメントは #,--(ハイフン2つ) /*  */ がある
CodeについてはUNIQUEユニークにしない、毎回同じ企業コードが入るかも

・テーブルを作成
CREATE TABLE Table_Dekidaka(
ID int(11) NOT NULL AUTO_INCREMENT,
Code int(5) NOT NULL,
Market text,
Name text,
Price int(11) ,
Volume int(14),
PreviousVolume int(14),
VolumePer float,
StockDate DATE,
CreateDate DATETIME,
Yobi text,
PRIMARY KEY (ID)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

>>オートインクリメントのIDは、PRIMARY KEY(ID)が必要。ないとエラーになる。

mysql> show tables;
mysql> show columns from Table_Dekidaka;

+----------------+----------+------+-----+---------+----------------+
| Field          | Type     | Null | Key | Default | Extra          |
+----------------+----------+------+-----+---------+----------------+
| ID             | int      | NO   | PRI | NULL    | auto_increment |
| Code           | int      | NO   |     | NULL    |                |
| Market         | text     | YES  |     | NULL    |                |
| Name           | text     | YES  |     | NULL    |                |
| Price          | int      | YES  |     | NULL    |                |
| Volume         | int      | YES  |     | NULL    |                |
| PreviousVolume | int      | YES  |     | NULL    |                |
| VolumePer      | float    | YES  |     | NULL    |                |
| StockDate      | date     | YES  |     | NULL    |                |
| CreateDate     | datetime | YES  |     | NULL    |                |
| Yobi           | text     | YES  |     | NULL    |                |
+----------------+----------+------+-----+---------+----------------+
11 rows in set (0.03 sec)

mysql> 
権限がないときは、権限を与える。
GRANT SHOW DATABASES ON *.* to maseda@localhost;
これでいいはず。もしこれでだめな場合は、必要な権限を与えて。

---
python
mysqldbを使用していたがmysql-connector-pythonが良いらしい。
pip install mysql-connector-python

pip list 一覧表示 OK

 

今日のエラー、Mysql、Can’t connect to local MySQL server

A・症状2021/01/06

iMacを再起動した後で、Anaconda NavigatorからPythonを実行した
するとエラーが発生。PythonでMysqlを使用しているエラーのようだ。
エラーの一部:Can’t connect to local MySQL server through
Mysqlサーバに接続できない

・対応

Mysqlを使用しているPythonでエラーが発生したとき、Can’t connect to local MySQL server through
たぶんMysqlが起動していないから(PCを起動した直後や再起動するとMysqlは停止しているからMysqlを起動する)
(1)mysqlサーバを起動する。ターミナルから実行する
$ mysql.server start
このrootはいつもの(秘密)パスワードで、CSV取り込みは、Test1030のパスワード

(2)Mysqlに接続する(以下は個別のアカウントmasedaを使用した場合。rootの場合はmysql -u root -p)
$ mysql -u maseda -p
Test1030(これは知られてもよい)のパスワード

(3)通常のMysqlコマンドやPythonから実行する
実行できた。

 

B SyntaxError

・症状

pythonを実行したらエラーメッセージが表示された

・エラーメッセージ

SyntaxError: invalid syntax

対応

指定された行の上の行の閉じカッコの数があっていなかった。
1個少なかったために、次の行でエラーが表示されていた。
test((a,a),(1,1,1)   <<<閉じカッコが足りない
testB()<<<ここでエラーが表示


test((a,a),(1,1,1))

pythonでTXTからCSV変換してMysqlへのインサート処理

#pythonメソッドは外部ファイルpy
#2020/12/21
#CSVをMysqlにインサート
#Test_Table_StockOption
#TXTからCSVに変換してCSVファイルを読み込んでMysqlのテーブルに登録を一括して行えるようにする。DB,テーブルは作成済とする。スタンドアローンでの利用

環境:MacOS BigSur、Python3、Mysql、JupiterLab Anaconda

#実行用

# MySQLdbのインポート
import MySQLdb
import os
import re
import sys
import datetime
import glob#ファイル一覧
import shutil#move

import methodMysql#個人用メソッド pyファイル
#本文は下にある。メソッドを先に記載しないと呼び出しでエラーになる。


#本文
########入力内容########################################################################
ifile='2020年12月23日AM7時39分.txt'#CSVはTXTから作成されるのでCSV名は不要
useTable='Table_StockOption'#Mysqlへ登録するテーブル、テスト用、通常用がある
useDate='2020/12/23'#オプション取り込みの日付
useMonth=1#月限 12月の作業はたいてい翌月である1月
########入力内容

#TXTをCSVに出力してからMysqlへ登録する。DB,テーブルは事前に用意されたものとする
###本文 ここでoutMojiMKIII()メソッドを使用している
path='/Users/toshiromaseda/Documents/2020年株関連/kabu_python/'
os.chdir(path)#ディレクトリ変更
print(os.getcwd())#ディレクトリ確認

csvfile='c_'+ifile.split('.')[0]+'.csv'

methodMysql.checkFile(ifile)#check 取り込み済みのファイルかどうかを調べる

try:
    ofile=open(csvfile,'tw') 
except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
   print("ファイルが見つかりません", e)
   #print("強制終了")
   sys.exit()#ファイルがなければ終了
except Exception as e: # Exceptionは、それ以外の例外が発生した場合
   print(e)

try:#ファイルが存在しないときのエラー処理try
    with open(ifile,'tr') as fin:
        for iline in fin:
            #ilineに、”コール”、”出来高”の文字がある行は無視するようにする
            #countで探すか 1行目、2行目は不要なのでDBにインサートしないための処理
            if iline.count('コール')>=1 or iline.count('出来高')>=1:
                continue#以下は実行されない
            try:
                ofile.write(methodMysql.outMojiMKIII(iline)+'\n')#MKIII改良版2020/12/18
                #次はMysqlに直接インサートするバージョンを作業する
            except Exception:
                print("do not")
        ofile.close()
except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
    print("ファイルが見つかりません。パス、ファイル名を確認してください", e)
    ofile.close()
    print("強制終了")
    sys.exit()#ファイルがなければ終了
except Exception as e: # Exceptionは、それ以外の例外が発生した場合
   print(e)

#CSVからMysqlへ CSVファイルがないと実行できない。重複チェックなし
#csvToMysql(difileはCSVファイル名,dtablename、doptionDate日付、dmonth月限)
#テスト用テーブルTest_Table_StockOption
methodMysql.csvToMysql(csvfile,useTable,useDate,useMonth)

#Testが終わったら試す。 単独実行可能 但し、ファイルの移動先チェックがないので、他で移動がないことをチェックする必要あり
methodMysql.fileMove(ifile,'./option_python_execute')
methodMysql.fileMove(csvfile,'./option_python_execute')

#表、グラフを出力する 単独実行可能
methodMysql.selectMysql('Table_StockOption')

print("終わりました。")

メソッド 外部ファイルにしたmethodMysql.py これをimport methodMysql として読み込む

#pythonUseMysql2.ipynbで使用
# MySQLdbのインポート
import MySQLdb
import os
import re
import sys
import datetime
import glob#ファイル一覧
import shutil#move

#株探の先物オプション記事について、特定文字列について空白をカンマに置換処理するためのメソッド
#def latterHalf(text):数字を後ろから探す
#def outMojiMKIII(text):空白をカンマに置換処理
#def csvToMysql(difile,dtablename,doptionDate,dmonth):
#def checkFile(filename):fileが存在するかチェック。パスは固定
#def fileMove(file,path):file移動
#def selectMysql(tablename):select 



#メソッドを別ファイルにした。
#文字列の後ろ側の数字を後ろから探し、抜けていた場合0を埋める
def latterHalf(text):
    textout=text
    pattern=re.compile('[0-9]+')#findで正規表現ができない
    i=0
    checkArray=[]#タプルを入れる配列
    while i>=0:#数字を探す
      m=pattern.search(textout, i)
      if m:
        #print(m.start())
        #print(m.end())
        #これをタプル配列に入れて、N,N-1で差が大きいときに0を入れる
        #print(m.span())
        checkArray.append(m.span())
        i = m.end()#m.start() + 1#m.end()
      else:
        break
    n=len(checkArray)
    if n>=2:#nは最低2こ必要 最後と最後の1こ前の
        #print("[n-1][0]",checkArray[n-1][0])#0番目の1個目 [0](0,1)
        #print("[n-2][1]",checkArray[n-2][1])#0番目の2個目
        #個数はNだけど配列の指定はそれより1小さいのでN-1となる
        if (checkArray[n-1][0]-checkArray[n-2][1])>=6:
            print("put抜けている")
            #checkArray[n-1][1]の後ろに挿入する
            texttmp=textout[:checkArray[n-2][1]+2]+ '0' + textout[checkArray[n-2][1]+2:]
            textout=texttmp
    output=textout
    return output
#end def

def outMojiMKIII(text):
    #空白を削除する前に、空白の個数を数える
    #株探の仕様が変わったらここを変える。2020/12/16
    kuro=re.compile('[  ]+')#半角と全角の空白置換 半角全角が[半角全角]として入っている
    
    if text.count(' ',0,15)>=13:
           #空白13個はプット
            opt='put'
            textout=text.strip()#先頭、末尾の空白、改行を削除する
    else:
            #コールの場合、2種類あるのでそれをチェックする
            textout=text.strip()#先頭、末尾の空白を削除する
            check=kuro.sub(',',textout)#半角全角の空白を置換
            count=check.split(",")
            #print ('len count:',len(count))
            if len(count)>=5:#配列が5個以上なら、call,putが含まれる       
                opt='callandput'
            else:
                opt='onlycall'
    pattern=re.compile('[0-9]+')#findで正規表現ができない
    if opt=='onlycall' or opt=='callandput':
        #次に、「call,putあり」OR「Callのみ」かをチェックする。
        #optSub='callandput' 'onlycall'
        #callのみを先に処理して、put側を調べる
        matchobj=re.search('[0-9]+',textout)#最初の数字を探す
        if matchobj:
            #print('マッチした文字列:'+matchobj.group())
            #print('マッチした文字列グループ:',matchobj.groups())
            #print( '開始位置'+str(matchobj.start()) )#先頭位置は0番として数える 3番目(4文字目)に見つかった
            #print( '終了位置'+str(matchobj.end()) )#終了位置は次の番目を含んでいるので実際は1を引いた数が終了位置
            #print(matchobj.span())#'マッチした文字列の (開始位置, 終了位置) のタプル'+
            #2番めの数字を探す
            secondMatch=pattern.search(textout,matchobj.end())#compileを使用してpatternで再度位置を指定して探す
            if secondMatch:
                #print( '開始位置2:'+str(secondMatch.start()) )#先頭から数えて10番目に次の数字が見つかった
                #1番目と2番めの文字数が5以上空いていたら数字が抜けている事がわかる。
                #ここに0を埋める処理を入れる
                if secondMatch.start()-matchobj.end() >=5:
                    print('値が抜けてる')
                    # hash = "355879ACB6"
                    # hash = hash[:4] + '-' + hash[4:]
                    #文字列の挿入。#1番目の文字の3文字目くらいに0を追加する。
                    texttmp=textout[:matchobj.end()+2]+ '0' + textout[matchobj.end()+2:]
                    textout=texttmp
        #put側のチェック。再度optでチェックする
        if opt=='onlycall':
            #置換して終わる
            output=kuro.sub(',',textout)+',,,'
        elif opt=='callandput':
            #print('callandputの処理')
            tmp=latterHalf(textout)#後半PUTの処理をして文字を返す
       
            #置換して終わる
            output=kuro.sub(',',tmp)
    elif opt=='put':
    #putのみの場合
        #3つのカンマを付ける
        tmp=latterHalf(textout)#後半PUTの処理をして文字を返す
        output=',,,'+kuro.sub(',',tmp)#>>,,,26250,285,-10,189
    #end if
 
    return output
### end def

def csvToMysql(difile,dtablename,doptionDate,dmonth):
#ここからSTART
#Mysqlに接続メソッドを入れる
# データベースへの接続とカーソルの生成
    connection = MySQLdb.connect(
        host='localhost',
        user='maseda',
        passwd='Test1030',#知られても問題ないパスワード
        db='Stock')
    cursor = connection.cursor()

    #csvファイル名
    ifile=difile
    
    #table
    tablename=dtablename#"Test_Table_StockOption"#テスト用テーブルを使用する

    #カラム名
    rowname="(Volume1,Change1,Price1,ExercisePrice,Price2,Change2,Volume2,Month,OptionDate,CreateDate,YOBI)"
    #VALUES (%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s)>>%dは%sにしないとエラーになった。

    #カラム変数
    month=dmonth#1#月限
    optionDate=doptionDate#"2020/12/22"#データ取得の日付、たいていCSVに記載の日付になる。
    
    dt_now=datetime.datetime.now()
    createDate=dt_now.strftime('%Y-%m-%d %H:%M:%S')#今日の日付時刻を入れて、取り込み実行の日付で良い。後で削除操作するときの目安くらいだから厳密ではない

    yobi=""#コメントがあればいれる。
    
    count=0
    #テーブルにデータを挿入する部分から書いていく
    #CSVを1行ごとに読み取り、列ごとにカラムに入れていく
    try:#ファイルが存在しないときのエラー処理try
        with open(ifile,'tr') as fin:
            for iline in fin:
                try:
                    #Mysqlに直接インサートするバージョンを作業する
                    # ここに実行したいコードを入力します

                    #cursor.execute("INSERT INTO Test_Table_StockOption (カラム,) VALUES(値,,,)")
                    #cursor.execute("INSERT INTO " + tablename + " " + rowname + " VALUES (%s,%s)", ("test1","test2"))
                    #count=count+1
                    tmp=iline.strip().split(",")#stripしてからsplit()だと理解している。 iline.split(",")のままだと改行が入ってくるのでstripで前後の空白と改行を削除する
                    #CSVのデータが空の場合は、値0を入れる
                    if tmp[0]=='':
                        tmp[0]=0
                    if tmp[1]=='':
                        tmp[1]=0
                    if tmp[2]=='':
                        tmp[2]=0
                    if tmp[3]=='':
                        tmp[3]=0
                    if tmp[4]=='':
                        tmp[4]=0 
                    if tmp[5]=='':
                        tmp[5]=0
                    if tmp[6]=='':
                        tmp[6]=0    
                    #テストテーブルにインサートする前に、確認する前に、Splitを確認する。
                    #print(count,tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6])
                    #%dにするとエラーになるのでINT型は%sにしておくとエラーにならない。なのでINTなのに%sとして記述してある。
                    cursor.execute("INSERT INTO " + tablename + " " + rowname + " VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)",\
                                   (tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6],month,optionDate,createDate,yobi))

                    #こっちだと、%dに値がないよとエラーになる。正しい記述のはずがパイソンではエラーになるようだ。
                    #cursor.execute("INSERT INTO " + tablename + " " + rowname + " VALUES (%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s)",\
                    #               (tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6],month,optionDate,createDate,yobi))

                except MySQLdb.Error as e:
                    print('MySQLdb.Error: ', e)
                    connection.rollback()#失敗したらもとに戻す。これだと途中で成功してもコミットされるので、1回でもエラーのときはBREAKのほうがいいかも。
                    print("強制終了MYSQL")
                    connection.close()
                    return
            #ofile.close()
        connection.commit()

    except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
        print("ファイルが見つかりません。パス、ファイル名を確認してください", e)
        ofile.close()
        sys.exit()#ファイルがなければ終了
    except Exception as e: # Exceptionは、それ以外の例外が発生した場合
       print(e)

    # 接続を閉じる
    connection.close()  

    print("Mysql書き込み終了")
#defここまで

#check file
def checkFile(filename):
    #他にもimport os os.listdir(path) というのもある
    files=glob.glob('./option_python_execute/*.txt')
    for file in files:
        #print(file)
        if filename in file:#ファイル名を含んでいればTRUE
            print('すでに取り込み済みのファイルです。')
            sys.exit()#return
#end def

def fileMove(file,path):
    shutil.move(file, path)#('./new.txt', './sample')
    print('file move',file)
#end def

def selectMysql(tablename):
# データベースへの接続とカーソルの生成
    connection = MySQLdb.connect(
        host='localhost',
        user='maseda',
        passwd='Test1030',#知られても問題ないパスワード
        db='Stock')
    cursor = connection.cursor()  
    try: 
        # ここに実行したいコードを入力します
        cursor.execute("SELECT SUM(Volume1) as callVolume1, ExercisePrice, SUM(Volume2) as putVolume2 FROM "+ tablename +\
                        " WHERE Month=1 GROUP BY ExercisePrice ORDER BY ExercisePrice Desc")

        #カラム名を取得
        #cursor.execute("show columns from Table_StockOption")

        # fetchall()で全件取り出し
        rows = cursor.fetchall()
        searchArray=[]#タプルで登録
        for row in rows:
          print(row[0],row[1],row[2])
          searchArray.append(row)  
            # print(row[Volume1]) ERROR

        #print(searchArray[0])#IDの情報:('ID', 'int', 'NO', 'PRI', None, 'auto_increment')
        #for srow in searchArray:
        #    print(srow)#
    
    except MySQLdb.Error as e:
        print('MySQLdb.Error: ', e)
    
    #表示
    connection.commit()
    connection.close()  
#end def

 

pythonでCSVをMysqlへのインサート処理

#pythonでCSVをMysqlへのインサート処理を入れたい
#2020/12/21
#CSVをMysqlにインサート
#Test_Table_StockOption
#CSVファイルを読み込んでMysqlのテーブルに登録を一括して行えるようにする
#
“””
考え方2020/12/22
TXTをCSVで出力
CSVファイルを読み込み
Mysqlに接続
ループしながらMysqlのテーブルに入れていく

現在はCSV出力まで終わっているので
CSVファイルを読み込み
テーブルにデータを挿入する部分から書いていく

・テーブルを作成例 Mysql

CREATE TABLE Test_Table_StockOption(
ID int(11) NOT NULL AUTO_INCREMENT,
Volume1 int(11),
Change1 int(11),
Price1 int(11),
ExercisePrice int(11) NOT NULL,
Price2 int(11),
Change2 int(11),
Volume2 int(11),
Month int(2),
OptionDate DATE,
CreateDate DATETIME,
YOBI text,
PRIMARY KEY (ID)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

・データを全部削除
delete from Table_StockOption;
・自動採番をリセット
ALTER TABLE Test_Table_StockOption AUTO_INCREMENT = 1;

#作業用動作確認用コード


# MySQLdbのインポート
import MySQLdb
import os
import re
import sys
import datetime


#TXTからCSV出力はここにあるとする。

#CSVファイルを読み込み
path='/Users/toshiromaseda/Documents/2020年株関連/kabu_python/'
os.chdir(path)#ディレクトリ変更
print("作業ディレクトリ:",os.getcwd())#ディレクトリ確認
ifile='c_2020年12月22日AM935.csv'#sys.argv[1] このスクリプトと同じ階層ならパスは不要 

#CSVの中身の例
#128,-5,29,27875,,,
#304,-5,40,27750,1530,0,1


#ここからSTART メソッドにするときは、ifileとtablename、optionDate、month月限を引数にしたほうがわかりやすい。
#Mysqlに接続メソッドを入れる
# データベースへの接続とカーソルの生成
connection = MySQLdb.connect(
    host='localhost',
    user='maseda',
    passwd='Test1030',#知られても問題ないパスワード
    db='Stock')
cursor = connection.cursor()

#table
tablename="Test_Table_StockOption"#テスト用テーブルを使用する

#カラム名
rowname="(Volume1,Change1,Price1,ExercisePrice,Price2,Change2,Volume2,Month,OptionDate,CreateDate,YOBI)"
#VALUES (%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s)

#カラム変数
month=1#月限
optionDate="2020/12/22"#データ取得の日付、たいていCSVに記載の日付になる。
dt_now=datetime.datetime.now()
createDate=dt_now.strftime('%Y-%m-%d %H:%M:%S')#今日の日付時刻を入れて、取り込み実行の日付で良い。後で削除操作するときの目安くらいだから厳密ではない

yobi=""#コメントがあればいれる。

count=0
#テーブルにデータを挿入する部分から書いていく
#CSVを1行ごとに読み取り、列ごとにカラムに入れていく
try:#ファイルが存在しないときのエラー処理try
    with open(ifile,'tr') as fin:
        for iline in fin:
            try:
                #Mysqlに直接インサートするバージョンを作業する
                # ここに実行したいコードを入力します
                
                #cursor.execute("INSERT INTO Test_Table_StockOption (カラム,) VALUES(値,,,)")
                #cursor.execute("INSERT INTO " + tablename + " " + rowname + " VALUES (%s,%s)", ("test1","test2"))
                count=count+1
                tmp=iline.strip().split(",")#stripしてからsplit()だと理解している。 iline.split(",")のままだと改行が入ってくるのでstripで前後の空白と改行を削除する
                #CSVのデータが空の場合は、値0を入れる
                if tmp[0]=='':
                    tmp[0]=0
                if tmp[1]=='':
                    tmp[1]=0
                if tmp[2]=='':
                    tmp[2]=0
                if tmp[3]=='':
                    tmp[3]=0
                if tmp[4]=='':
                    tmp[4]=0 
                if tmp[5]=='':
                    tmp[5]=0
                if tmp[6]=='':
                    tmp[6]=0    
                #テストテーブルにインサートする前に、確認する前に、Splitを確認する。
                #print(count,tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6])
                #%dにするとエラーになるのでINT型は%sにしておくとエラーにならない。なのでINTなのに%sとして記述してある。
                cursor.execute("INSERT INTO " + tablename + " " + rowname + " VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)",\
                               (tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6],month,optionDate,createDate,yobi))
                
                #こっちだと、%dに値がないよとエラーになる。正しい記述のはずがパイソンではエラーになるようだ。
                #cursor.execute("INSERT INTO " + tablename + " " + rowname + " VALUES (%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s)",\
                #               (tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6],month,optionDate,createDate,yobi))
                
                #print("count",len(tmp))#カンマがあれば全部カウントされる。全部7つ
                
            except MySQLdb.Error as e:
                print('MySQLdb.Error: ', e)
                connection.rollback()#失敗したらもとに戻す。これだと途中で成功してもコミットされるので、1回でもエラーのときはBREAKのほうがいいかも。
                
        #ofile.close()
    connection.commit()
    
except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
    print("ファイルが見つかりません。パス、ファイル名を確認してください", e)
    ofile.close()
except Exception as e: # Exceptionは、それ以外の例外が発生した場合
   print(e)

# 接続を閉じる
connection.close()  

print("Mysql書き込み終了")
##ここまで

 

MysqlにCSVファイルをインサート

環境:MacOS Bigsur
Mysql8
CSV カンマ区切り UTF8
Pythonを使ってテキストファイルをCSVに出力して、
そのCSVファイルをMysqlのテーブルにターミナル手動でインサート処理する。
コマンドラインで実行する
LOAD DATA LOCAL INFILE

注意点はMySQLバージョン8では、デフォルトでは無効化されている。
mysql> SELECT @@local_infile;
を実行して「1」になっているかを確認する。「0」なら無効なので有効にする必要がある。
以下、下方に記載

参考サイト
http://jigsaw.hatenablog.jp/entry/2013/06/12/113016

参考、エラーになった
https://mita2db.hateblo.jp/entry/2020/01/13/163218
MySQL 8.0 で LOAD DATA LOCAL INFILE は無効化されている

以下のDBとテーブルは作成済み
作成方法については、他の記事を参照してほしい

ユーザ:maseda
pass:Tes****
DB:Stock
Table:Table_StockOption
・カラム構成
ID:id , int auto_increment、自動採番
出来高1 Volume1
前日比1 Change1
価格1 Price1
行使価格 ExercisePrice
価格2 Price2
前日比2 Change2
出来高2 Volume2
月限 Month , 例 12月限 12
取引日付、株探掲載日付 OptionDate ,date , DATE(NOW()) >> 2014-01-15
テーブル取り込み作成日 CreateDate ,datetime, NOW() >>2014-01-15 17:05:43
予備YOBI (テキスト),text


CSVファイルをテーブルのカラムにインサート処理する。
事前に与える値
「月限」はファイル名に記載していないので、取り込み毎に与える。
今後ファイル名に12月限みたいに記載してそこから取得するようにするか?

また「取引日付、株探掲載日付 OptionDate」については、任意の日付を与える。
「テーブル取り込み作成日」は、NOW()で与える。

@1から@7はCSVのカラムの左側からの順番で、列数は7つ
なおIDカラムが存在するが自動採番なので何も指定しない

mysqlのコマンドラインで実行する。ファイル名とテーブル名、カラム等を変更。
CSVは7つあり、テーブルのカラムは12こある。そしてIDは自動採番設定あり。
CSVの1番目を@1として該当のカラムVolume1に入れる。
SET Volume1=@1
以降CSVの@番号をカラム名に入れていく。

LOAD DATA LOCAL INFILE "/Users/toshiromaseda/Documents/2020年株関連/kabu_python/c_pythontest_2020年12月17日.csv"
INTO TABLE Table_StockOption
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
(@1,@2,@3,@4,@5,@6,@7)
SET Volume1=@1, Change1=@2, Price1=@3, ExercisePrice=@4,
Price2=@5,Change2=@6,Volume2=@7,Month='1',OptionDate='2020/12/01',
CreateDate=NOW(),YOBI='';

画像CSVの構成7つの列がある

Number
テーブルカラム一覧画像、Volume1にCSVの1列目が入る。IDは自動採番なのでCSVにはない

キャプチャ

LOAD DATAを実行するとエラーになった。

mysql> use Stock;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> LOAD DATA LOCAL INFILE "/Users/toshiromaseda/Documents/2020年株関連/kabu_python/c_pythontest_2020年12月17日.csv"
-> INTO TABLE Table_StockOption
-> FIELDS TERMINATED BY ','
-> LINES TERMINATED BY '\n'
-> (@1,@2,@3,@4,@5,@6,@7)
-> SET Volume1=@1, Change1=@2, Price1=@3, ExercisePrice=@4,
-> Price2=@5,Change2=@6,Volume2=@7,Month='1',OptionDate='2020/12/01',
-> CreateDate=NOW(),YOBI='';
ERROR 3948 (42000): Loading local data is disabled; this must be enabled on both the client and server sides
mysql>

エラーになった。↑
LOAD DATA INFILE LOCAL は セキュリティ上のリスクになるため、デフォルトでは無効化されているらしい。

・以下の2つを設定する
1ターミナル
$ mysql -u root -p –local_infile=1

2mysql側
mysql> SET GLOBAL local_infile=on;

確認
SELECT @@local_infile;

mysql> SELECT @@local_infile;
+----------------+
| @@local_infile |
+----------------+
| 1 |
+----------------+
1 row in set (0.00 sec)

1になっているのでOK。

user:masedaでMysqlに接続して再度確認して問題なし。

mysql> SELECT @@local_infile;
+----------------+
| @@local_infile |
+----------------+
| 1 |
+----------------+
1 row in set (0.00 sec)

mysql> LOAD DATA LOCAL INFILE "/Users/toshiromaseda/Documents/2020年株関連/kabu_python/c_pythontest_2020年12月17日.csv"
-> INTO TABLE Table_StockOption
-> FIELDS TERMINATED BY ','
-> LINES TERMINATED BY '\n'
-> (@1,@2,@3,@4,@5,@6,@7)
-> SET Volume1=@1, Change1=@2, Price1=@3, ExercisePrice=@4,
-> Price2=@5,Change2=@6,Volume2=@7,Month='1',OptionDate='2020/12/01',
-> CreateDate=NOW(),YOBI='';
Query OK, 85 rows affected, 222 warnings (0.04 sec)
Records: 85 Deleted: 0 Skipped: 0 Warnings: 222

 

warningはあるがCSVデータは登録されているようだ。

mysql> select OptionDate ,CreateDate,YOBI from Table_StockOption limit 5;
+------------+---------------------+------+
| OptionDate | CreateDate | YOBI |
+------------+---------------------+------+
| 2020-12-01 | 2020-12-18 10:59:06 | |
| 2020-12-01 | 2020-12-18 10:59:06 | |
| 2020-12-01 | 2020-12-18 10:59:06 | |
| 2020-12-01 | 2020-12-18 10:59:06 | |
| 2020-12-01 | 2020-12-18 10:59:06 | |
+------------+---------------------+------+
5 rows in set (0.00 sec)

 

一旦、データを消して再度CSVを登録してワーニングを見る
ワーニングを表示させるには
show warnings;

データを全部削除
mysql> delete from Table_StockOption;
Query OK, 85 rows affected (0.02 sec)

再度、Loadを実行
そして
show warnings;
warningが表示された。
どうやら、値がない(空)でワーニングが表示されたようだ。空でもいいので
これは無視していいようだ。
INTで空の場合は0が入っている
| Warning | 1366 | Incorrect integer value: ” for column ‘Volume1’ at row 85 |
| Warning | 1366 | Incorrect integer value: ” for column ‘Change1’ at row 85 |
| Warning | 1366 | Incorrect integer value: ” for column ‘Price1’ at row 85 |

mysql> select count(*) from Table_StockOption;
+----------+
| count(*) |
+----------+
| 85 |
+----------+



mysql> select * from Table_StockOption limit 3;
+-----+---------+---------+--------+---------------+--------+---------+---------+-------+------------+---------------------+------+
| ID | Volume1 | Change1 | Price1 | ExercisePrice | Price2 | Change2 | Volume2 | Month | OptionDate | CreateDate | YOBI |
+-----+---------+---------+--------+---------------+--------+---------+---------+-------+------------+---------------------+------+
| 128 | 95 | 0 | 1 | 32000 | 0 | 0 | 0 | 1 | 2020-12-01 | 2020-12-18 11:03:16 | |
| 129 | 52 | 0 | 2 | 30750 | 0 | 0 | 0 | 1 | 2020-12-01 | 2020-12-18 11:03:16 | |
| 130 | 12 | 0 | 3 | 30250 | 0 | 0 | 0 | 1 | 2020-12-01 | 2020-12-18 11:03:16 | |
+-----+---------+---------+--------+---------------+--------+---------+---------+-------+------------+---------------------+------+
3 rows in set (0.00 sec)

 

IDはリセットしていないので、削除した後に追加すると次の番号がふられるから、
実際の行数とは一致しない。

・mysql auto_increment リセット
ALTER TABLE テーブル名 AUTO_INCREMENT = 1;

なので、データをdeleteしてから実行するとよいはず。
delete from Table_StockOption;
ALTER TABLE Table_StockOption AUTO_INCREMENT = 1;

mysql> delete from Table_StockOption;
Query OK, 85 rows affected (0.01 sec)

mysql> ALTER TABLE Table_StockOption AUTO_INCREMENT = 1;
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0

 

>>削除してリセットまで済。次は、必要なデータを順次取り込む。今ここ、2020-12-18、11時27分
—適宜、ファイル名を変更していく

mysqlコマンド

LOAD DATA LOCAL INFILE "/Users/toshiromaseda/Documents/2020年株関連/kabu_python/c_pythontest_2020年12月17日.csv"
INTO TABLE Table_StockOption
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
(@1,@2,@3,@4,@5,@6,@7)
SET Volume1=@1, Change1=@2, Price1=@3, ExercisePrice=@4,
Price2=@5,Change2=@6,Volume2=@7,Month='1',OptionDate='2020/12/01',
CreateDate=NOW(),YOBI='';

 

 

MySQLでDB、テーブルを作成する、MacOS BigSur 2020年12月

MySQLのセキュリティ設定している人はここは飛ばす

$マークはMacのターミナルを使用している。
ターミナルは、アプリの「その他」の中にある。(何故かわかりにくいところに入れてある)

mysqlサーバを起動する
$ mysql.server start
Starting MySQL
. SUCCESS!

止めるときは
$ mysql.server stop

次にセキュリティ設定
このサイトを参考にすると良い
https://style.potepan.com/articles/19020.html

MySQLのセキュリティ設定

>>>>>>>>>>>>>>>>>>>以下入力した内容 ここから↓

$ mysql_secure_installation



Securing the MySQL server deployment.

Connecting to MySQL using a blank password.

VALIDATE PASSWORD COMPONENT can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD component?

Press y|Y for Yes, any other key for No: y

There are three levels of password validation policy:

LOW Length >= 8
MEDIUM Length >= 8, numeric, mixed case, and special characters
STRONG Length >= 8, numeric, mixed case, special characters and dictionary file

Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 0  >>0:LOWとした。本番環境なら2だ
Please set the password for root here.

New password:   >>パスワードを入れる

Re-enter new password:  >>パスワードの確認

Estimated strength of the password: 50
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.


Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Success.

By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.


Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
- Dropping test database...
Success.

- Removing privileges on test database...
Success.

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.

All done!

 

>>>>>>>>>>>>>>>>>>>>ここまで

mysqlにRootでログインする。

$ mysql -u root -p
Enter password:   >>先程登録したパスワード
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.22 Homebrew

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

 

exitで抜ける
mysql> exit
Bye

ユーザの作成・削除

user:maseda
pass:Test1030 >>ここのパスワードは知られても気にしない。このパスワードを他で使わないから。

ユーザの作成
まずは
rootでログインする
mysql -u root -p
(pass)
以下はmysqlコマンドとして入力する。masedaユーザを作成
一人でしか使わないが、今後誰かと共同作業があるかもしれないので勉強のために
ユーザを作る。

create user ‘maseda’@localhost identified by ‘Test1030’;
作成したユーザの確認

select user, host from mysql.user;

mysql> select user, host from mysql.user;
+------------------+-----------+
| user | host |
+------------------+-----------+
| maseda | localhost |
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+
5 rows in set (0.00 sec)

 

MySQLの設定をしている人はここから作業をする。

root権限でユーザにグローバルレベルでcreate権限を与える。すべてのDBで使える。
制限するときは、DB名を指定するが今はしない。

権限を与える。必要なときに必要な分を与える
grant create on *.* to maseda@localhost;
GRANT SELECT,UPDATE,INSERT,DELETE ON *.* to maseda@localhost;
GRANT DROP,CREATE VIEW,ALTER,EXECUTE,INDEX,SHOW DATABASES,SHOW VIEW,FILE ON *.* to maseda@localhost;

exitでrootを抜ける。

→次はここから、2020/12/15
ユーザでログイン
mysql -u maseda -p
psssはTes*****にした。上に記載。このパスワードはデモ用なので知られてOK

次にデータベースを作成して、テーブルを作る。
そしてCSVファイルを読み込む

自動採番の例 auto_increment
>>create table staff(id int auto_increment, name varchar(10), index(id));

今回作成するDB(Stock)とテーブル(Table_StockOption)を作成

株探のオプション記事の数値をDB化する。
作成の例
DB:Stock
Table:Table_StockOption
・カラム
ID:id , int auto_increment、自動採番
出来高1 Volume1
前日比1 Change1
価格1 Price1
行使価格 ExercisePrice
価格2 Price2
前日比2 Change2
出来高2 Volume2
月限 Month , 例 12月限 12
取引日付、株探掲載日付 OptionDate ,date , DATE(NOW()) >> 2014-01-15
テーブル取り込み作成日 CreateDate ,datetime, NOW() >>2014-01-15 17:05:43
予備 (テキスト),text

//正負を表す ‘-‘ や ‘+’ を記述することができる。+10の+記号はINT型で可能
挿入時は+記号はない。10となり、マイナスは-10となる
NULLは処理速度が遅くなるのでできるだけ使わない。空にしたくないなら-1とか’unknown’とか入れる
大量のデータがないときはそれほど考慮しなくてよいだろう。

・ユーザはmaseda

・DBを作成
CREATE DATABASE Stock DEFAULT CHARACTER SET utf8mb4;

・DBを指定する
use Stock;

・テーブルを作成
CREATE TABLE Table_StockOption(
ID int(11) NOT NULL AUTO_INCREMENT,
Volume1 int(11),
Change1 int(11),
Price1 int(11),
ExercisePrice int(11) NOT NULL,
Price2 int(11),
Change2 int(11),
Volume2 int(11),
Month int(2),
OptionDate DATE,
CreateDate DATETIME,
YOBI text,
PRIMARY KEY (ID)
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

>>PRIMARY KEY(ID)が必要。ないとエラーになる。

mysql> show tables;
+-------------------+
| Tables_in_stock |
+-------------------+
| Table_StockOption |
+-------------------+

mysql> show columns from Table_StockOption;
ERROR 1142 (42000): SELECT command denied to user ‘maseda’@’localhost’ for table ‘table_stockoption’
mysql>
この場合権限がないので、権限を与える。
GRANT SHOW DATABASES ON *.* to maseda@localhost;
これでいいはず。もしこれでだめな場合は、必要な権限を与えて。
以下はカラム一覧を表示

mysql> show columns from Table_StockOption;
+---------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+----------+------+-----+---------+----------------+
| ID | int | NO | PRI | NULL | auto_increment |
| Volume1 | int | YES | | NULL | |
| Change1 | int | YES | | NULL | |
| Price1 | int | YES | | NULL | |
| ExercisePrice | int | NO | | NULL | |
| Price2 | int | YES | | NULL | |
| Change2 | int | YES | | NULL | |
| Volume2 | int | YES | | NULL | |
| Month | int | YES | | NULL | |
| OptionDate | date | YES | | NULL | |
| CreateDate | datetime | YES | | NULL | |
| YOBI | text | YES | | NULL | |
+---------------+----------+------+-----+---------+----------------+
12 rows in set (0.01 sec)

 

これでテーブルの作成まで終わった。
次は、株探からコピペしたテキストをCSVファイルに置き換えて
mysqlに取り込む作業。
まずは、PythonでCSVファイルに変更するスクリプトを書く

BigSurにbrew,mysqlインストール、環境MacOSXからBigSurにアップグレードしたら

詳細な説明はこっち
https://style.potepan.com/articles/19020.html

簡潔な説明はこっち
https://qiita.com/fuwamaki/items/194c2a82bd6865f26045

mysql –versionを実行したところmysqlはまだインストールされていなかった。
次にbrewのバージョンを確認、
$ brew -v

以下のようなエラーが発生した。調べるとMac OSをBigSurにバージョンアップしたことが原因で、
brewもアップグレードが必要
>>エラーの内容

Traceback (most recent call last):
11: from /usr/local/Homebrew/Library/Homebrew/brew.rb:23:in `<main>'
10: from /usr/local/Homebrew/Library/Homebrew/brew.rb:23:in `require_relative'
9: from /usr/local/Homebrew/Library/Homebrew/global.rb:37:in `<top (required)>'
8: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
7: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
6: from /usr/local/Homebrew/Library/Homebrew/os.rb:3:in `<top (required)>'
5: from /usr/local/Homebrew/Library/Homebrew/os.rb:21:in `<module:OS>'
4: from /usr/local/Homebrew/Library/Homebrew/os/mac.rb:58:in `prerelease?'
3: from /usr/local/Homebrew/Library/Homebrew/os/mac.rb:24:in `version'
2: from /usr/local/Homebrew/Library/Homebrew/os/mac.rb:24:in `new'
1: from /usr/local/Homebrew/Library/Homebrew/os/mac/version.rb:26:in `initialize'
/usr/local/Homebrew/Library/Homebrew/version.rb:368:in `initialize': Version value must be a string; got a NilClass () (TypeError)

以下の3つのコマンドを順に実行した。brew doctorは必須ではないかも、、、

$ brew update
>>暫く待つ、アップデートが裏で始まっている。5分ほど待つ
$ brew doctor
>>Warningがでるけどよくわかんないのでそのまま
$ brew upgrade
>>暫く待つ、画面上に色々とインストール状況が表示される

やっとインストールできた。

$ brew --version
Homebrew 2.6.2
Homebrew/homebrew-core (git revision dc0df; last commit 2020-12-15)
Homebrew/homebrew-cask (git revision 6217f8; last commit 2020-12-15)

mysqlをインストール
$ brew install mysql

バージョンを確認
$ mysql –version
mysql Ver 8.0.22 for osx10.16 on x86_64 (Homebrew)
##################やっとインストールできた。