我是 Rust 新手,我正在尝试使用 postgres 板条箱。我能够通过对表名称进行硬编码来创建表,但在尝试从变量传递表名称时,代码总是会出现恐慌。
rustc --version 1.36.0
cargo --version 1.36.0
postgres = "0.15"
Run Code Online (Sandbox Code Playgroud)
fn main() {
let conn = Connection::connect("postgresql://postgres:postgres@localhost/db1",
TlsMode::None).unwrap();
let tname = "message";
conn.execute("CREATE TABLE IF NOT EXISTS $1 (
id SERIAL PRIMARY KEY,
title VARCHAR NOT NULL,
body VARCHAR,
)", &[&tname]).ok().expect("Table message creation failed");
Run Code Online (Sandbox Code Playgroud)
fn main() {
let conn = Connection::connect("postgresql://postgres:postgres@localhost/db1",
TlsMode::None).unwrap();
let tname = "message";
conn.execute("CREATE TABLE IF NOT EXISTS $1 (
id SERIAL PRIMARY KEY,
title VARCHAR NOT NULL,
body VARCHAR,
)", &[&tname]).ok().expect("Table message creation failed");
Run Code Online (Sandbox Code Playgroud)
您不能使用占位符(例如$1
)将表名替换为查询。
占位符的功能之一是允许查询准备一次,然后执行多次。这节省了每次要使用查询时规划查询的开销,这可能是巨大的。但是,如果数据库甚至不知道正在查询哪个表,则不可能计划查询。
如果需要在运行时动态插入表名,则需要在将 SQL 传递到数据库之前在 Rust 中执行此操作:
let sql = format!("CREATE TABLE IF NOT EXISTS {} (
id SERIAL PRIMARY KEY,
title VARCHAR NOT NULL,
body VARCHAR,
)", tname);
Run Code Online (Sandbox Code Playgroud)
如果表名是从用户输入传入的,请不要忘记通过事先验证来防止 SQL 注入。
另请注意,恐慌是由于使用.ok().expect(....)
.
ok()
将获取执行 SQL 的结果并将其转换为Option
. 如果结果是错误,它将被丢弃,因此您永远看不到可能有助于您诊断问题的错误消息。Result
直接实现expect
,其优点是不会丢弃错误,而是将其显示为 Panic 的一部分。所以,你会更好:
conn.execute(sql, &[] as &[String]).expect("Failed creating table");
Run Code Online (Sandbox Code Playgroud)
但是,如果 SQL 语句很可能会失败,那么您最好检查结果并更优雅地处理它,而不是使程序崩溃。