VBAで配列をソート 選択ソート

バブルソートは時間がかかる
quick sortはササッと書くのは難しい
ので選択ソート

こんな感じで

integer と long

VBAでは
integer -32768 から 32767
long  -2147483648 から 2147483647
vb.netでは
integer -2147483648 から 2147483647
long -923372036854775808 から 9223372036854775807

vbaで
dim i as long
for i=0 to ..
と書いていたがvb.netで同様に書くとなぜだかインテリセンスによく怒られる
vbaのlongはvb.netではinteger
今更だけど

複数ステップのOLEDBエラー nvarchar(max) 改行

SQLserverテーブルのnvrachar(max)のカラムに対して
ODBC接続のレコードセット取って

Str=”文字” & vbCrLf
rs!カラム=Str
rs.update
など更新や追加行うと複数ステップの・・・エラー

OLEDB接続では起きない
nvarchar(max)をmaxを500など変更すれば起きない
cn.execute “insert into・・・values・・・” では起きない

サロゲートペア SQLserverの場合

以前もMySQLで書いたけど
AccessからSQLServerへサロゲート文字保存について

AccessはVBエディターに表示はできないけどテーブル、フォームに表示保存可能
SQLserverも保存できる

接続文字を書いてexecuteメソッドで
insert into Table(column) values(“サロゲートペア文字”)
とVBAから更新クエリ発行すると保存できない

OLEDBはだめ
oledbはhttps://docs.microsoft.com/ja-jp/sql/connect/oledb/features/utf-16-support-in-oledb-driver-for-sql-server?view=sql-server-2017
難しいけどだめだと書いてあるようです

ODBCならといろいろ試したけどこれも今のところだめです
ODBCからリンクテーブルにしてフォーム作って入力すると可能なのだがなぜ?
接続文字列にオプションか何かあるのかな?引き続き要調査

OLE DB

詳しくはわかりませんが何年か前から
Microsoft OLE DB Provider for SQL Server(SQLOLEDB) 
はもうサポートしないから新規開発に使用するのはやめてほしい
とMicrosoftがアナウンスしているが今でも使えています
でも突然消えると困るので調べてみると
代わりに
Microsoft OLE DB Driver for SQL Server(MSOLEDBSQL) 
をリリースしてるようです
問題はSQLOLEDBはOSに付属してるので何も考えずに良かったけどMSOLEDBは別途インスト必要らしいです
挙動も少し違うようで安全性は向上する、計算列の操作が今まで甘かったけど今度は厳しく行きますよ という感じのことがアナウンスされてた
今日開発機にインストして使ってみましたがaccdbは特に問題なく動きました。
OSは64bitですがAccessが32なのでx86をインストだろうと思ったらX64でした
接続文字もSQLOLEDBをMSOLEDBSQLに書き換えるだけで良いようです
アプリ配布先にはインストされてないのでパッケージ作るとき困るけどSQLOLEDB消えてから考えよう

VBAからSQL ServerのIdentity取得

これは時々必要になるのですが
scope_identity() , ident_current(‘Table’) , @@Identity
の3つの方法があるが他のセッションの影響を受けない scope_identity() が推奨と検索すると出てきます。

しかしVBAからADO ADODBでレコードセットを取って
前略
cn.execute “insert into table・・・”
rs.open “select scope_identity() as ID”,cn,adopendynamic,adlockoptimistic
としても取得してくれないのでしかたなく
rs.open “select ident_current(‘Table’) as ID”,cn,adopendynamic,adlockoptimistic
で取得していました

cursorlocationがserverサイドでdynamicを要求した場合だけ取得できないのに気がつきました
ほかの組み合わせは大丈夫のようです
しかしこのレコードセットのcursortypeは何を要求しようと結局forwardonlyに調整されます
テーブルやPK等で自動調節?
ならばなぜdynamic要求の場合だけXなのでしょう。動的だから?

Null 空文字列

Null でよく勘違いする
SQLserverテーブルでもMYSQLテーブルでも 数値型のカラムにnullを入れることはできる
テーブル設計でnullを許可にすれば良いだけの話

変数にnullを代入するのは不可能な場合もある

VBAでは
dim Var as long
var=null
は不可能、stringはOK stringもだめです
variantだけ可能

ではSQLserverでも同じだろうと思ったら
declare @Var int
set @Var=null
select @Var
とクエリを発行したらNullが返ってきた

では宣言のみで代入なしは?(=初期値?)
SQLserver
declare @Var int
select @Var
は Null
nvarcharでも同様

VBAは複雑
dim Var as long
debug.print Var
はなんと 0

dim Var as string
debug.print Var
は 空白
調べるとこれNullではなく ”” つまり空文字列

役立ちそうにない知識でしょうが一応書き留めておきます

また日付

今日 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)
としないとだめ

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

VBAからselect into #table できることもある

Dim Parm As Long
Param= **
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
cn.ConnectionString = “接続文字列”
cn.Open

cn.Execute “drop table if exists #table”
cn.Execute “select * into #table from Other where column=” & Param
cn.execute “update #table set ・・・”
以下略

シンプルにこれだけならば#テーブルは作成されますが

Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = New ADODB.Connection
cn.ConnectionString = “接続文字列”
Set rs = New ADODB.Recordset
cn.Open

rs.open “SQL文”,cn,・・・
以下略

cn.Execute “drop table if exists #table”
cn.Execute “select * into #table from Other where column=” & Param
cn.execute “update #table set ・・・”
以下略

と複雑になるとオブジェクトは無効ですとエラーです。

なぜかはわかりませんがレコードセットが必要ならprivate sub を別に作って
callにしたらうまくいきます。