Mysql備忘録

最近Mysqlさわっていないので忘れている。いやさわってないから忘れるのではなく歳のせいかも。
とにかく

Mysqlのコンソールで
クエリを間違えてばかりで
-> から
mysql> へ戻りたいときのメタコマンドは
\c

カラム名にスペースとか入ってうまくクエリできないときは
select column name from table
はバッククォートの
シングルクォートの ‘ と間違えないように
ちなみにSQLserverでは
select [column name] from table

集計クエリ カウント

重複は除外してカウント、重複あっても全カウント 両方出したいとき
SQLserver、MySQLなら
select GroupColumn,Count(distinct TargetColumn),Count(TargetColumn) from Table group by GroupColumn
と簡単に出る

ACCESSでは?

このクエリはACCESSではできないようなのでいろいろ試したが今のところクエリ一文ではできていない
一度クエリでカウントして保存してさらにこれをソースにカウントしたカラムをカウントする のイメージで….

select GroupColumn as Group1,Count(TargetColumn) as Count1 from Table group by GroupColumn,TargetColumn
これをQ_1で保存して
select Group1,Count(Count1) as CountDistinct from Q_1 group by Group1
これでdistinct countができる

もう一つ全カウント
select GroupColumn as Group1,Count(TargetColumn) as CounAll from Table group by GroupColumn
のクエリQ_2を保存して

Q_1、Q_2 の連結クエリを作成する  の2段構え
もっといい方法があるのかもしれないが今のところこれしか思いつかない

バックエンドがSQLserverやMySQLならACCESSから一番上のパススルークエリの方が楽かな?

また日付

今日 2018-10-19 の日付で

select case when current_timestamp>’2018-10-18′ then ‘true’ else ‘false’ end;
はSQLserverでもMYSQLでもtrue

select case when current_timestamp>’2018-10-20′ then ‘true’ else ‘false’ end;
はSQLserverでもMYSQLでもfalse

でもVBAでは
debug.print iif(now>”2018-10-18”,true,false)
はfalseとなってしまう
debug.print iif(now>cdate(“2018-10-18”),true,false)
としないとだめ

日付は型宣言や型変換するようにしないといけないですかね

Nullには要注意 と Alterカラムデータ型


カラム2が数値型の場合
select * from Table where カラム2<>8
ではカラム2がnullを選択しない nullを選びたいときは別に条件を明示の必要ありか


似ているけど
カラム2は文字型
select * from Table where カラム2<>‘8’
では空文字列のカラム2を選択する
空文字列とNullが混在するテーブルがあるときは要注意

mysqlもSQLserverも同じ

あとカラムデータ型変更
SQLserverは
alter Table TableA alter Column ColumnA nvarchar(255) null;
Mysqlは
alter table TableA modify Column ColumnA varchar(255) null;

MySQL8

知らない間にアップデートがありました。
今回メジャーアップデートですので早いうちにアップデートしないと遅れるほど難しくなりそう
ということで数日たいへんでした。
まずGTIDスレーブからアップデート
マイナーアップデートのようにzip解凍、上書きしてmysql_upgradeしたら??できない
クリーンインストしてマスターからdumpしてリストアしたらエラーだらけ
何をやってもエラーだらけなのでもうひとつ念のため5.7の非GTIDサーバを立ててから
もうえいやとサーバもアップデート

いろいろやったけどうちの場合は
非GTID5.7からdumpする際 –default-character-set=binary のオプション
GTID8へのリストアは —-default-character-set=utf8mb4 -f のオプション
が一番エラーが少ないような・・5.7はutf8で立ち上げて途中utf8mb4に変更

サーバがなんとかリストアできたので今度は8のマスターから8のGTIDスレーブへリストア
これもエラーでまくりですが
なぜか
GTID8からdumpのoption   –default-character-set=binary
GTID8へのリストアのoption –default-character-set=utf8
がエラーが一番少なかった。エラーはトリガーやストアドの中の日本語の様な気が?
なんとか今日から稼働しました。

従来の2倍の性能らしいです。

defaultの文字コードはutf8mb4 4バイト絵文字、サロゲート文字がOKです。
のはずですが入力時ODBCエラー やはりODBC8が必要なのでしょうか
今のところODBC8は64bit版のみです

CTE、再帰クエリが使えるようになってます。

あとIDの再利用をしないようになったとかどこかで見ましたが未確認です。

GTIDのdumpですがGTIDへリストアする場合と非GTIDへリストアする場合とoptionを変えないといけないのは面倒くさいです。
MySQL3からMySQL5へのアップデートもたいへんでしたが今度もほどほどに難易度高かったです。

追記 mysqldumpのオプション
GTIDからGTIDへ  –triggers –routines –events
GTIDから非GTIDへ –set-gtid-purged=OFF

CursorLocation CursorType LockType

recordsetプロパティが意図通りにならないことがあるのはわかりました。

https://blogs.msdn.microsoft.com/nakama/2008/10/16/ado/
の下の方に表が出ています。
SQLserverの場合だと思います。

同じようにMysql5.7で調べてみると

結果がSQLserverと少し違います。

赤文字は意図と結果が違う
斜めはSQLserverと結果が違う

aduseclientにした時点でstatic決定は同じでした。
aduseserverでstaticになってますがrecordset.countは-1でした。

クエリ強制終了

MySQLで終わらないクエリ、ループなどを強制終了するには
show processlist;
をよく見て該当のクエリを見つけて
kill クエリのid;

SQLserverでは
exec sp_who
でクエリを見つけて
kill spid

とかく日付は難しい

SQLserverでもMySQLでもVBAでも
2018/1/1を文字の様に’2018/1/1’とか”2018/1/1”とか書けば日付として認識してくれる
と思っていたけど日付の比較で・・

SQLserverで
select iif(‘2018/1/4’>’2018-1-1′,’true’,’false’)
はtrueと思っていたらfalseを返します。文字と認識?
もちろん
declare @ParamS datetime,@ParamE datetime
select @paramS=’2018-1-1′
select @ParamE=’2018/1/31′
select iif(‘2018/1/4′ between @paramS and @paramE,’true’,’false’)
ときちんと宣言代入すればtrueです。

あるいは
select iif(‘2018/1/4’>cast(‘2018-1-1′ as datetime),’true’,’false’)
はtrueです。
片方だけでも日付型にしてあげるともう一方も日付と見てくれるようです。

VBAでもMySQLでも同じ挙動でした。
MySQLにiif関数はないのでnullif関数で
select nullif(‘2018-1-4′,’2018/1/4’);
select nullif(‘2018-1-4’,cast(‘2018/1/4′ as datetime)); 
で確認
上は別物と見なされ’2018-1-4’
下は同一と見なされnull
です。

if exists

mysqlでもsqlserverでも
訂正 SQLserverのみ
MySQLはテーブルがあらかじめないとダメでした。

drop table if exists Table
select * into Table from otherT where ・・・

は便利と思うのですが同じことをAccessのローカルテーブルにしようと
VBAでcurrentproject.connection に
cn.execute “drop table if exists Table” とやっても通用しません

しばらく悩みましたが
on error resume next
docmd.setwarnings false
cn.execute “drop table Table”
docmd.setwarnings true
でとりあえずはなんとか