Better-SQLite3 參數綁定詳解
在使用 better-sqlite3
進行數據庫操作時,參數綁定是一個非常重要的概念。它不僅提高了代碼的可讀性和安全性,還能有效防止 SQL 注入攻擊。本文將詳細介紹如何在 better-sqlite3
中使用匿名參數和命名參數,并展示一些實際應用示例。
匿名參數
匿名參數使用問號(?
)作為占位符,并通過位置來綁定參數值。你可以直接傳遞參數值,或者將它們放在數組中傳遞。
示例代碼
const Database = require('better-sqlite3');
const db = new Database('mydb.sqlite');// 創建表
db.exec(`CREATE TABLE IF NOT EXISTS people (id INTEGER PRIMARY KEY AUTOINCREMENT,first_name TEXT NOT NULL,last_name TEXT NOT NULL,age INTEGER NOT NULL)
`);// 準備插入語句
const stmt = db.prepare('INSERT INTO people (first_name, last_name, age) VALUES (?, ?, ?)');// 插入數據 - 直接傳遞參數
stmt.run('John', 'Smith', 45);
console.log('Inserted John Smith.');// 插入數據 - 使用數組傳遞參數
stmt.run(['Jane', 'Doe', 30]);
console.log('Inserted Jane Doe.');// 插入數據 - 混合方式傳遞參數
stmt.run(['Alice'], ['Brown', 28]);
console.log('Inserted Alice Brown.');// 釋放資源
stmt.finalize();// 查詢所有記錄以驗證插入結果
const selectStmt = db.prepare("SELECT * FROM people");
const rows = selectStmt.all();
rows.forEach((row) => {console.log(`ID: ${row.id}, First Name: ${row.first_name}, Last Name: ${row.last_name}, Age: ${row.age}`);
});
selectStmt.finalize();// 關閉數據庫連接
db.close();
console.log('Database connection closed.');
在這個示例中,我們創建了一個 people
表,并使用匿名參數插入了幾條記錄。可以看到,無論是直接傳遞參數還是通過數組傳遞參數,都可以實現同樣的效果。
命名參數
命名參數允許你為每個參數指定一個名稱,這樣可以更清晰地標識每個參數的作用。SQLite 支持三種命名參數語法:@foo
、:foo
和 $foo
,這些都受 better-sqlite3
支持。
示例代碼
const Database = require('better-sqlite3');
const db = new Database('mydb.sqlite');// 創建表
db.exec(`CREATE TABLE IF NOT EXISTS people (id INTEGER PRIMARY KEY AUTOINCREMENT,first_name TEXT NOT NULL,last_name TEXT NOT NULL,age INTEGER NOT NULL)
`);// 準備插入語句 - 使用 @ 符號命名參數
const stmt1 = db.prepare('INSERT INTO people (first_name, last_name, age) VALUES (@firstName, @lastName, @age)');
stmt1.run({firstName: 'John',lastName: 'Smith',age: 45
});
console.log('Inserted John Smith using @ notation.');// 準備插入語句 - 使用 : 符號命名參數
const stmt2 = db.prepare('INSERT INTO people (first_name, last_name, age) VALUES (:firstName, :lastName, :age)');
stmt2.run({firstName: 'Jane',lastName: 'Doe',age: 30
});
console.log('Inserted Jane Doe using : notation.');// 準備插入語句 - 使用 $ 符號命名參數
const stmt3 = db.prepare('INSERT INTO people (first_name, last_name, age) VALUES ($firstName, $lastName, $age)');
stmt3.run({firstName: 'Alice',lastName: 'Brown',age: 28
});
console.log('Inserted Alice Brown using $ notation.');// 查詢所有記錄以驗證插入結果
const selectStmt = db.prepare("SELECT * FROM people");
const rows = selectStmt.all();
rows.forEach((row) => {console.log(`ID: ${row.id}, First Name: ${row.first_name}, Last Name: ${row.last_name}, Age: ${row.age}`);
});// 關閉數據庫連接
db.close();
console.log('Database connection closed.');
在這個示例中,我們展示了如何使用不同符號的命名參數插入數據。無論使用哪種符號,都能達到相同的效果。
混合匿名參數與命名參數
你可以在同一個 SQL 語句中混合使用匿名參數和命名參數。在這種情況下,匿名參數按順序綁定,而命名參數通過對象傳遞。
示例代碼
const Database = require('better-sqlite3');
const db = new Database('mydb.sqlite');// 創建表
db.exec(`CREATE TABLE IF NOT EXISTS people (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL,age INTEGER NOT NULL)
`);// 準備插入語句 - 混合使用匿名參數和命名參數
const stmt = db.prepare('INSERT INTO people (name, age) VALUES (@name, ?)');// 插入數據 - 先傳遞匿名參數,再傳遞命名參數
stmt.run(30, { name: 'Henry' });
console.log('Inserted Henry with age 30.');// 查詢所有記錄以驗證插入結果
const selectStmt = db.prepare("SELECT * FROM people");
const rows = selectStmt.all();
rows.forEach((row) => {console.log(`ID: ${row.id}, Name: ${row.name}, Age: ${row.age}`);
});// 關閉數據庫連接
db.close();
console.log('Database connection closed.');
在這個示例中,我們展示了如何在一個 SQL 語句中同時使用匿名參數和命名參數。
數據類型轉換
better-sqlite3
在 JavaScript 和 SQLite 之間自動進行數據類型的轉換,具體如下:
SQLite | JavaScript |
---|---|
NULL | null |
REAL | number |
INTEGER | number or BigInt |
TEXT | string |
BLOB | Buffer |
示例代碼
以下是一個展示不同類型數據轉換的示例:
const Database = require('better-sqlite3');
const db = new Database('mydb.sqlite');// 創建表
db.exec(`CREATE TABLE IF NOT EXISTS data_types (id INTEGER PRIMARY KEY AUTOINCREMENT,real_value REAL,integer_value INTEGER,text_value TEXT,blob_value BLOB)
`);// 準備插入語句
const insertStmt = db.prepare('INSERT INTO data_types (real_value, integer_value, text_value, blob_value) VALUES (?, ?, ?, ?)');// 插入不同類型的值
insertStmt.run(3.14, // REAL42, // INTEGER'Hello, World!', // TEXTBuffer.from('Binary Data') // BLOB
);// 釋放資源
insertStmt.finalize();// 查詢所有記錄以驗證插入結果
const selectStmt = db.prepare("SELECT * FROM data_types");
const rows = selectStmt.all();
rows.forEach((row) => {console.log(`ID: ${row.id}, Real Value: ${row.real_value}, Integer Value: ${row.integer_value}, Text Value: ${row.text_value}, Blob Value: ${row.blob_value.toString()}`);
});// 關閉數據庫連接
db.close();
console.log('Database connection closed.');
總結
- 匿名參數:使用問號(
?
)作為占位符,通過位置綁定參數。 - 命名參數:支持
@foo
、:foo
和$foo
三種命名參數語法,通過對象綁定參數。 - 混合使用:可以在同一 SQL 語句中混合使用匿名參數和命名參數。
- 數據類型轉換:
better-sqlite3
自動在 JavaScript 和 SQLite 之間進行數據類型的轉換。
通過合理使用參數綁定,可以提高代碼的可讀性、安全性和維護性。希望這篇文章對你有所幫助!如果有更多問題或需要進一步的幫助,請隨時提問。