標準愚痴出力

個人的なIT作業ログです。もしかしたら一般的に参考になることが書いているかもしれません(弱気

5DB x Go言語 "database/sql" プレースホルダーまとめ

DB プレースホルダーor バインド変数
SQLite3 ?
MySQL ?
SQL Server @VARNAME
Oracle :VARNAME
PostgreSQL $1, $2...

プレースホルダー・バインド変数に与える値は ExecContext 関数の args という可変長パラメータに与えるが、作法に少し差異がある。

func (c *Conn) ExecContext(ctx context.Context, sql string, args ...any) (Result, error)

SQLite3, MySQL

大抵のDBドライバーは、args として、プレースホルダーを使った順番に値を与えればよい

SQL

UPDATE  emp
   SET  ENAME = ?
 WHERE  EMPNO = ?  AND  ENAME = ?  AND  JOB = ?  AND  MGR = ?  AND  date(HIREDATE) = date(?)  AND  SAL = ?  AND  COMM is NULL  AND  DEPTNO = ?

args

(1) "ahaha4" (2) 8002 (3) "ahaha3" (4) "ihihi2" (5) 9003 (6) time.Date(1972, time.May, 23, 0, 0, 0, 0, time.Location("")) (7) "" (8) 30

SQL Server

値そのものを並べるのではなく、sql.Named を使ってバインド変数名と値をペアでならべてやらなければいけない

SQL

UPDATE  testtbl
   SET  DTTM = @v1
 WHERE  TESTNO = @v2  AND  DTTM = @v3  AND  DT = @v4  AND  TM = @v5  AND  SDTTM = @v6  AND  DTTM2 = @v7

args

(v1) time.Date(2024, time.May, 25, 13, 45, 34, 0, time.Location("")) (v2) 10 (v3) time.Date(2024, time.May, 25, 13, 45, 33, 0, time.Location("")) (v4) "2024-05-26 00:00:00 +00:00" (v5) "0001-01-01 14:53:26 +00:00" (v6) time.Date(2024, time.May, 25, 14, 53, 0, 0, time.Location("")) (v7) time.Date(2024, time.May, 25, 14, 52, 13, 133000000, time.Location(""))

values という []any 型配列に値が格納されている場合、次のように args を用意する。

args := make([]any,0,len(values))
for i, v := range values {
    args = append(args, sql.Named(fmt.Sprintf("v%d", i+1), v))
}

Oracle

バインド変数を使うが、sql.Named の使用は必須ではない。使った順で並べてもよい ( SQL-Bless では処理を共通化させるため、SQL Server と同様に sql.Named を使っている )

PosgreSQL

$1,$2.. に割り当てる値そのものを順番に args として与えればよい。

余談

SQL-Bless ではデータベースごとの差異は

https://github.com/hymkor/sqlbless/tree/master/dialect

以下で管理している。

以上