如何将参数传递给db.exec

时间:2014-10-19 11:13:22

标签: postgresql go

考虑db.Exec语句

  

db.Exec(“INSERT INTO $ 1 values($ 2,$ 3,to_timestamp($ 4),var1,var2,var3,var4)

^^但是如果我想做像

那样的话
  

db.Exec(“INSERT INTO table_name_ $ 1 values($ 2,$ 3,to_timestamp($ 4),var1,var2,var3,var4)

它不起作用,$ 1会附加到表名而不是$ 1的值,我该如何将它添加到查询中?

1 个答案:

答案 0 :(得分:2)

由于您说第一个示例有效,一种解决方案是将完整的表名作为参数传递,事先进行字符串连接:

db.Exec("INSERT INTO $1 values($2,$3)", "table_name_"+tbl, "this", "that")

您还可以使用fmt.Sprintf%s手动格式化字符串,如评论中所示。

准备好的陈述

我有点惊讶你的第一个例子有效,因为这不是Postgres中的有效语法。如果使用表名作为参数创建预准备语句,则会返回语法错误:

# PREPARE fooplan (text, bool, numeric) AS
    INSERT INTO $1 VALUES($2, $3);
ERROR:  syntax error at or near "$1"
LINE 2:     INSERT INTO $1 VALUES($2, $3);

而您提供的第二个示例也会将$1附加到表的名称,因此库的行为正确:

# PREPARE fooplan (text, bool, numeric) AS
    INSERT INTO table_name_$1 VALUES($2, $3);
ERROR:  relation "table_name_$1" does not exist
LINE 2:     INSERT INTO table_name_$1 VALUES($2, $3);

所以在你的第一个例子中,库可能对你有利,但这可能不是你应该过分依赖的东西。

最安全的长期解决方案可能是使用fmt.Sprintf进行必要的转义,以格式化表名,然后在Exec调用中使用它:

sql := fmt.Sprintf(`INSERT INTO table_name_%s values($1,$2,to_timestamp($3))`, tbl)
db.Exec(sql, params...)