アナログCPU:5108843109

ゲームと音楽とプログラミング(酒と女とロックンロールのノリで)

('ω') < イザユケエンジニャー

ユニークなインデックスが存在しないテーブルを求める

MySQLを前提として書いています


先日弊社のphpMyAdminを3.x系から4.x系にアップデートしまして
「PRIMARY/UNIQUEのいずれのインデックスも張られていないテーブルのレコードは編集/削除不可」という問題まっとうな仕様変更にぶち当たったので、
そのとき影響範囲の調査に使った
「PRIMARY/UNIQUEのいずれのインデックスも張られていないテーブル一覧」を求めるクエリをメモ。

…ピンポイントすぎてもう使わない気がしなくもないですが、「○○なテーブル一覧」レベルであれば出すこともありそうなので、参考として、一応。

SELECT    `TABLES`.`TABLE_NAME`, `COLUMNS`.`COLUMN_KEY`
FROM      `information_schema`.`TABLES`
LEFT JOIN `information_schema`.`COLUMNS`
  ON      `TABLES`.`TABLE_NAME` = `COLUMNS`.`TABLE_NAME`
  AND     `COLUMNS`.`COLUMN_KEY` IN ('UNI', 'PRI')
WHERE     `TABLES`.`TABLE_SCHEMA` = '【データベース名】'
  AND     `COLUMNS`.`COLUMN_KEY` IS NULL
GROUP BY  `TABLES`.`TABLE_NAME`

ユニークキーが存在しないテーブルっていう仕様がそもそもだめなのでは、というアレ

Ingress倉敷ミッションデイに参加してきました

倉敷駅からさっくりクリアできる6つを選んでやってきました。通し番号としては1~6を順にですね。
f:id:honey8823:20160928130425p:plain

時々、無関係と思ってハックした直後のポータルが指定されて手間取ったりはしました…。
ミッションデイ当日だと焼き合いもすごいのでヒートシンク刺す隙すらなかったりして。

これでミッションデイは3回目の参加。メダルが銀になるのが楽しみ。

ingressミッションレビュー:ViaLux : Setouchi , JP

ViaLux参加記念に。
f:id:honey8823:20160928125439p:plain

https://ingressmm.com/?find=ViaLux%20%3A%20Setouchi%20%2C%20JP

ミッションとは関係ないのですが、最後のmeasurementが終わった直後のfactionチャット。
とてもすき。
f:id:honey8823:20160928125919p:plain:w400
普段から挨拶とか応答とか掛け声的な感じで「えんらーい」を見ることはありますが、こんなに並ぶの初めて見た。
ところでRESはこういう「ウェーイ」みたいなのを何て言うんだろう…?

Ingress東京ミッションデイに参加してきました

いやいや、対象ミッション多すぎでしょ!!!ということで6つ厳選してきました。

f:id:honey8823:20160928124152p:plain
国会議事堂→六本木→渋谷→台場→スカイt…スカイツリー東京都庁
という突然のななどら聖地巡礼。(もちろんメダルは逆順)

この中には特に難しいミッションはありませんでしたが、中には皇居一周とかいうマゾゲー難易度の高いものもあったそうです。

ちなみにうちの旦那は当日に23区内ミッションをすべて番号順にクリアし、
後日文京と町田もやはり番号順にこなしておりました…。

ingressミッションレビュー:AEGIS NOVA TOKYO MEMORY

かっこいいメダルがあったので、こちらもAegisNova記念に。
f:id:honey8823:20160928123636p:plain

新宿をぐるっと回る程度のお手軽ミッションでした。
(こちらを見る限り、現時点で3つは削除されている模様…?)
https://ingressmm.com/?find=AEGIS%20NOVA%20TOKYO%20MEMORY

アノマリー時は同シリーズのミッションを作成されている方のようなので、その他も是非。
https://ingressmm.com/?find=Pocoty&findby=1

ingressミッションレビュー:AegisNova : Tokyo , JP

AegisNova参加記念。受付の後にさっくり回ってきました。
f:id:honey8823:20160928123022p:plain

地図はこちら。
https://ingressmm.com/?find=AegisNova%20%3A%20Tokyo%20%2C%20JP

スムーズに回れるよう工夫してあるミッションでとても良かったです。

また、最後のミッションは2つあり、夜間(台場公園に入れない時間帯)は「12'」の方を選ぶとOKだそうです。

ingressミッションレビュー:風景印を巡る旅

全52個あるシリーズミッションですが、愛知・岐阜が中心で、沖縄・東京にも少しずつ。
東京から6つ抜粋しました。
https://ingressmm.com/?find=%E9%A2%A8%E6%99%AF%E5%8D%B0%E3%82%92%E5%B7%A1%E3%82%8B%E6%97%85

f:id:honey8823:20160928121552p:plain
はんこモチーフに弱いっ。

ミッション自体は、「最寄駅から郵便局までのルート」的なものも多く、プレイしやすかったです。
テーマがあるミッションですし、楽しめました。

全然関係ないのですが、このミッション中に
スマホが発熱してどうしようもない時はウィダーインゼリーが保冷剤(兼非常食)になる」ということに気付き、
以後暑い日にingressするときは持ち歩いてます。

駅メモ #13:マスターオブ沖縄と遠征三昧

石川、埼玉に続いて沖縄もマスターしてきました!

f:id:honey8823:20160926173756p:plain:w400

一つだけ離れた位置にある廃駅(嘉手納)は、中城城址まで行けば取れました。

他の県については、
東京があと2駅、神奈川があと4駅です。うまく調整すれば山梨あたりとまとめて同じ日にマスターオブ称号取れるんじゃないかと欲張って考え中。

また、瀬戸内方面にも遠征してきて、
京都に寄り道して地下鉄イベントは完了、アクティビティイベントも3地域すべてアクセス。

アクティヴレイドコラボもそこそこスタートダッシュしてきました。
ポイント稼ぎはもちろんですが、れいこさんを無事上限80にしてお仕事回数稼ぎ中。
「頼りにしてくれた」称号は一番乗りいただきました!
f:id:honey8823:20160926173928p:plain:w400
f:id:honey8823:20160926173934p:plain:w400

コラボガチャは大変引きが良かったです。
運を使い果たした気が…。(翌日の遠征先で行きたかったお店が臨時休業だったりというレベルのトラブルには多々見舞われました)
19回引いて7回れいこさんですからね。ラッピングも5つは引けましたし。



進捗は今日時点でこんな感じ。

f:id:honey8823:20160926173952p:plain:w400

前回(8/1)からの比較

  • 駅 2448 → 2778(+330)
  • 路線 308 → 339(+31)
  • 都道府県 28 → 30(+2)
  • コンプ路線 136 → 156(+20)

所持でんことLv ()内は前回比 ☆は凸完了

[S]セリア 8/75
[A]メロ 30/65 (Lv5up)
[D]ルナ 41/80 (Lv1up / 上限5up) ☆
[T]みろく 7/65 (上限5up)
[S]レイカ 16/60
[T]シャルロッテ 59/60 (Lv4up / 上限5up)
[T]シーナ 7/65 (上限5up)
[A]さや 8/60
[S]もえ 61/80 (Lv24up) ☆
[T]いろは 33/50
[D]しいら 8/65
[D]もぼ 10/55
[D]いずな 75/75 (Lv5up / 上限5up)
[S]ふぶ 60/60
[A]りんご 36/80 (Lv2up) ☆
[T]ニャッシュ 15/80 ☆
[T]ダッチュー 50/50 (Lv24up)
[T]いちほ 39/75 (Lv2up)
[A]イムラ 50/60 (上限5up)
[T]にころ 54/55
[S]しぐれ 7/60 (上限10up)
[A]レン 8/75
[T]みらい 10/55
[D]ベアトリス 9/60 (上限5up)
[S]うらら 31/55 (Lv15up)
[A]ほこね 9/65
[T]やちよ 15/70
[A]リオナ 7/55
[T]チコ 18/55
[A]レーノ 7/70
[D]ありす 70/70
[T]コタン 24/80 ☆
[T]エリア 18/50
[S]ひいる 15/80 (上限10up) ☆
[D]いおり 14/80 (Lv5up) ☆
[S]ミオ 6/55
[S]みこと 22/60 (Lv11up)
[D]くに 6/55
[T]るる 15/75 (上限10up)
[A]ハル 8/55
[D]にちな 9/60
[A]そら 8/75 (上限5up)
[S]アサ 65/65
[A]さいか 13/55 (上限5up)
[A]Liko 6/75 (new)
[D]れいこ 58/80 (new) ☆


ニャッシュ、りんご、コタン、もえ、いおりに続きルナ、ひいる、れいこも上限突破完了。



自分用育成メモ:

今はとにかくれいこさん育成中。
(お仕事回数3000回を一番乗りしてみたいというやや不純な動機で)
とはいえLvがそこそこ上がってきたので、新駅を多く取るようなときは別の子に吸わせようかな。
ルナ>りんご>いちほ>うらら>メロ くらいの優先度で。

テーブルごとのサイズを調べる方法

MySQL
サイズというか容量というか使用量というか。アレ。

参考:MySQLのデータベースやテーブルのサイズを確認する方法 - Little Braver
http://little-braver.com/379/

SELECT
  `TABLE_SCHEMA`   -- DB名
 ,`TABLE_NAME`     -- テーブル名
 ,`TABLE_ROWS`     -- レコード数
 ,`AVG_ROW_LENGTH` -- レコードあたりの平均サイズ?
 ,FLOOR((`DATA_LENGTH` + `INDEX_LENGTH`) / 1024) AS `all_kb` -- 合計サイズ
 ,FLOOR(`DATA_LENGTH` / 1024) AS `data_kb`                   -- データサイズ
 ,FLOOR(`INDEX_LENGTH` / 1024) AS `index_kb`                 -- インデックスサイズ
FROM
  `information_schema`.`tables `
WHERE
  `TABLE_SCHEMA` IN ('データベース名1','データベース名2', ...)
ORDER BY
  `TABLE_SCHEMA`
 ,`TABLE_NAME`

InnoDBの場合、行数なんかは不正確な値が出る場合もあります。
サイズもだいたいページ単位(16KB)で出てくる模様。
ちょっと困る。

正確な(というか物理的な)サイズを調べる方法もあるようですが、
InnoDBだとテーブル単位で調べるようなことはできそうにないかな…。

参考:MySQLのデータベースの容量を調べる - ハマログ
https://blog.e2info.co.jp/2013/05/24/mysql%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AE%E5%AE%B9%E9%87%8F%E3%82%92%E8%AA%BF%E3%81%B9%E3%82%8B/


データベースサイズの調べ方はこちら。
honey8823.hateblo.jp

CSVを読み込み二次元配列に格納するプロシージャ・改

前にも同じようなのを作って使っていたんですが、
CSVにカンマや改行が含まれていると機能しないとかいうクソっぷりだったので、
大幅に改修しました。
あと、UTF-8CSVに対応したい事案があったのでそれも合わせて。
(改修というか別物に近い)


参考:UTF-8形式のテキストファイルから読み込む - Office TANAKA
http://officetanaka.net/excel/vba/file/file10.htm

参考:CSVの読み込み方法 - エクセルの神髄
http://excel-ubara.com/excelvba5/EXCEL111.html


途中、改行コードを調整している箇所がありますので、環境によって適切な感じに書き変えてください。
(詳しい解説は記事末尾に)

さて、以下がプロシージャですが
使う前に、VBEの ツール>参照設定 にて
Microsoft ActiveX Data Objects」を探してチェックを入れておきます。
バージョンは一番新しいものでOKでしょう。

'*
'* CSVを読み込み二次元配列に格納
'*
'* in  sCsvFile  CSVファイルまでのフルパス
'*     sCharset  文字コード(Shift_JIS, UTF-8, ...)
'* out CsvRead() CSVの中身(二次元配列)
'*
Public Function CsvRead(ByVal sCsvFile As String, Optional ByVal sCharset As String = "Shift_JIS") As String()

    Dim lDatNum As Long
    
    Dim sTmp As String
    Dim sTmpDat As String
    Dim sLine() As String
    Dim sRet() As String
    Dim lQuoteCount As Long

    Dim i As Long
    Dim j As Long
    Dim k As Long
    
    Dim streamAdodb As ADODB.stream
    
    'ファイルの存在を調べる
    If Not CreateObject("Scripting.FileSystemObject").FileExists(sCsvFile) Then
        Exit Function
    End If
    
    'ADODB.Stream生成
    Set streamAdodb = New ADODB.stream
    
    With streamAdodb
        'テキストモード、文字コードセット
        .Type = adTypeText
        .Charset = sCharset
        
        'Streamオープン
        .Open
        
        'ファイル読み込み
        .LoadFromFile (sCsvFile)
        sTmp = .ReadText
        
        'Streamクローズ
        .Close
    End With
    
    Set streamAdodb = Nothing

    '改行コードの調整&一行ごとに配列に移す
    sTmp = Replace(sTmp, vbCrLf, vbCr)
    sLine = Split(sTmp, vbLf)
    
    'データ数を求める(最後の行が空行の場合はカウントしない)
    If sLine(UBound(sLine)) = "" Then
        lDatNum = UBound(sLine)
    Else
        lDatNum = UBound(sLine) + 1
    End If
    
    '戻り値の枠をつくる
    ReDim sRet(0 To lDatNum - 1, 0 To 0)

    '一行ごとに処理
    For i = 0 To lDatNum - 1
        
        ' さっき調整した改行を元に戻す
        sLine(i) = Replace(sLine(i), vbCr, vbCrLf)
        
        j = 0
        lQuoteCount = 0
        sTmpDat = ""

        For k = 1 To Len(sLine(i))
            Select Case Mid(sLine(i), k, 1)
                Case "," '「"」が偶数なら区切り、奇数ならただの文字
                    If lQuoteCount Mod 2 = 0 Then

                        If UBound(sRet, 2) < j + 1 Then
                            ReDim Preserve sRet(0 To lDatNum - 1, 0 To j)
                        End If
                        sRet(i, j) = adjustQuote(sTmpDat)

                        j = j + 1
                        lQuoteCount = 0
                        sTmpDat = ""
                    Else
                        sTmpDat = sTmpDat & Mid(sLine(i), k, 1)

                    End If
                Case """" '「"」のカウントをとる
                    lQuoteCount = lQuoteCount + 1
                    sTmpDat = sTmpDat & Mid(sLine(i), k, 1)
                Case Else
                    sTmpDat = sTmpDat & Mid(sLine(i), k, 1)
            End Select
        Next

        '最終列の処理

        If UBound(sRet, 2) < j Then
            ReDim Preserve sRet(0 To lDatNum - 1, 0 To j)
        End If
        sRet(i, j) = adjustQuote(sTmpDat)

        j = j + 1
        lQuoteCount = 0
        sTmpDat = ""
    Next

    CsvRead = sRet

End Function
Private Function adjustQuote(ByVal strTmpDat As String)

    '「""」のみであれば空にする
    If strTmpDat = """""" Then
        strTmpDat = ""
    End If
    
    '「""」を「"」で置換
    strTmpDat = Replace(strTmpDat, """""", """")
    '前後の「"」を削除
    If Left(strTmpDat, 1) = """" And Right(strTmpDat, 1) = """" And Len(strTmpDat) >= 2 Then
        strTmpDat = Mid(strTmpDat, 2, Len(strTmpDat) - 2)
    End If
    
    adjustQuote = strTmpDat
End Function

改行コードの調整について。
ここでは、CSVのレコードごとの改行が「LF」、レコード内に含まれる改行が「CRLF」だったので、

  • CRLFをCRに置換してからLFごとに区切ってレコードとする
  • 区切った後のレコードについて、CRをCRLFに置換し直す

というステップを踏んでいます。
必要に応じて調整してください。
(両方とも同じ改行コードとかだと困る…)

'<抜粋>改行コードの調整&一行ごとに配列に移す
sTmp = Replace(sTmp, vbCrLf, vbCr)

'<抜粋>さっき調整した改行を元に戻す
sLine(i) = Replace(sLine(i), vbCr, vbCrLf)