ユニークなインデックスが存在しないテーブルを求める
※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ミッションレビュー:ViaLux : Setouchi , JP
ViaLux参加記念に。
https://ingressmm.com/?find=ViaLux%20%3A%20Setouchi%20%2C%20JP
ミッションとは関係ないのですが、最後のmeasurementが終わった直後のfactionチャット。
とてもすき。
普段から挨拶とか応答とか掛け声的な感じで「えんらーい」を見ることはありますが、こんなに並ぶの初めて見た。
ところでRESはこういう「ウェーイ」みたいなのを何て言うんだろう…?
ingressミッションレビュー:AEGIS NOVA TOKYO MEMORY
かっこいいメダルがあったので、こちらもAegisNova記念に。
新宿をぐるっと回る程度のお手軽ミッションでした。
(こちらを見る限り、現時点で3つは削除されている模様…?)
https://ingressmm.com/?find=AEGIS%20NOVA%20TOKYO%20MEMORY
アノマリー時は同シリーズのミッションを作成されている方のようなので、その他も是非。
https://ingressmm.com/?find=Pocoty&findby=1
ingressミッションレビュー:AegisNova : Tokyo , JP
AegisNova参加記念。受付の後にさっくり回ってきました。
地図はこちら。
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
はんこモチーフに弱いっ。
ミッション自体は、「最寄駅から郵便局までのルート」的なものも多く、プレイしやすかったです。
テーマがあるミッションですし、楽しめました。
全然関係ないのですが、このミッション中に
「スマホが発熱してどうしようもない時はウィダーインゼリーが保冷剤(兼非常食)になる」ということに気付き、
以後暑い日にingressするときは持ち歩いてます。
駅メモ #13:マスターオブ沖縄と遠征三昧
石川、埼玉に続いて沖縄もマスターしてきました!
一つだけ離れた位置にある廃駅(嘉手納)は、中城城址まで行けば取れました。
他の県については、
東京があと2駅、神奈川があと4駅です。うまく調整すれば山梨あたりとまとめて同じ日にマスターオブ称号取れるんじゃないかと欲張って考え中。
また、瀬戸内方面にも遠征してきて、
京都に寄り道して地下鉄イベントは完了、アクティビティイベントも3地域すべてアクセス。
アクティヴレイドコラボもそこそこスタートダッシュしてきました。
ポイント稼ぎはもちろんですが、れいこさんを無事上限80にしてお仕事回数稼ぎ中。
「頼りにしてくれた」称号は一番乗りいただきました!
コラボガチャは大変引きが良かったです。
運を使い果たした気が…。(翌日の遠征先で行きたかったお店が臨時休業だったりというレベルのトラブルには多々見舞われました)
19回引いて7回れいこさんですからね。ラッピングも5つは引けましたし。
進捗は今日時点でこんな感じ。
前回(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-8のCSVに対応したい事案があったのでそれも合わせて。
(改修というか別物に近い)
参考: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)