db_sqlite
Обёртка для базы данных SQLite более высокого уровня. Этот интерфейс реализован и для других баз данных.
Основное использование
Основной порядок использования этого модуля:
- Открыть соединение с базой данных
- Выполнить SQL-запрос
- Закрыть соединение с базой данных
Подстановка параметров
Все модули db_* поддерживают одинаковую форму подстановки параметров. То есть, используется ? (вопросительный знак) для обозначения места, куда нужно поместить значение. Например:
sql"INSERT INTO my_table (colA, colB, colC) VALUES (?, ?, ?)"
Открытие соединения с базой данных
import db_sqlite
# user, password, database name can be empty.
# These params are not used on db_sqlite module.
let db = open("mytest.db", "", "", "")
db.close() Создание таблицы
db.exec(sql"DROP TABLE IF EXISTS my_table")
db.exec(sql"""CREATE TABLE my_table (
id INTEGER,
name VARCHAR(50) NOT NULL
)""") Вставка данных
db.exec(sql"INSERT INTO my_table (id, name) VALUES (0, ?)",
"Jack") Пример побольше
import db_sqlite, math
let db = open("mytest.db", "", "", "")
db.exec(sql"DROP TABLE IF EXISTS my_table")
db.exec(sql"""CREATE TABLE my_table (
id INTEGER PRIMARY KEY,
name VARCHAR(50) NOT NULL,
i INT(11),
f DECIMAL(18, 10)
)""")
db.exec(sql"BEGIN")
for i in 1..1000:
db.exec(sql"INSERT INTO my_table (name, i, f) VALUES (?, ?, ?)",
"Item#" & $i, i, sqrt(i.float))
db.exec(sql"COMMIT")
for x in db.fastRows(sql"SELECT * FROM my_table"):
echo x
let id = db.tryInsertId(sql"""INSERT INTO my_table (name, i, f)
VALUES (?, ?, ?)""",
"Item#1001", 1001, sqrt(1001.0))
echo "Inserted item: ", db.getValue(sql"SELECT name FROM my_table WHERE id=?", id)
db.close() Примечание
Этот модуль не реализует никаких функций ORM, таких как отображение типов из схемы. Вместо этого для каждой строки возвращается seq[string].
Обоснование:
- Это близко к тому, что многие БД предлагают напрямую (char**)
- Это скрывает количество поддерживаемых типов БД
(int? int64? decimal до 10 знаков? геокоординаты?)
3. Это удобно, когда вам нужно только передать данные куда-то ещё (вывод, логирование, поместить данные в новый запрос)
См. также
- Модуль db_odbc для обёртки базы данных ODBC
- Модуль db_mysql для обёртки базы данных MySQL
- Модуль db_postgres для обёртки базы данных PostgreSQL
Импорты
- sqlite3, macros, db_common, since
Типы
DbConn = PSqlite3
- Оборачивает соединение с базой данных. Исходный код Редактировать
Row = seq[string]
- Строка набора данных.
NULLзначения базы данных будут преобразованы в пустую строку. Исходный код Редактировать InstantRow = PStmt
- Детекторы, которые могут использоваться для получения текста столбца строки по требованию. Исходный код Редактировать
SqlPrepared = distinct PStmt
- Идентификатор подготовленных запросов Исходный код Редактировать
Процедуры
proc `[]`(row: InstantRow; col: int32): string {...}{.inline, raises: [], tags: [].}-
Возвращает текст для заданного столбца строки.
См. также:
- итератор instantRows пример кода
proc len(row: InstantRow): int32 {...}{.inline, raises: [], tags: [].}-
Возвращает количество столбцов в строке.
См. также:
- итератор instantRows пример кода
proc finalize(sqlPrepared: SqlPrepared) {...}{.discardable, raises: [], tags: [].}- Исходный код Редактировать
proc dbQuote(s: string): string {...}{.raises: [], tags: [].}- Экранирует символ
'(одинарная кавычка) до''. Потому что одинарная кавычка используется для определенияVARCHARв SQL.Пример:
doAssert dbQuote("'") == "''''" doAssert dbQuote("A Foobar's pen.") == "'A Foobar''s pen.'"Исходный код Редактировать proc tryExec(db: DbConn; stmtName: SqlPrepared): bool {...}{. tags: [ReadDbEffect, WriteDbEffect], raises: [].}- Исходный код Редактировать
proc bindParam(ps: SqlPrepared; paramIdx: int; val: int32) {...}{.raises: [DbError], tags: [].}- Связывает int32 со специфицированным paramIndex. Исходный код Редактировать
proc bindParam(ps: SqlPrepared; paramIdx: int; val: int64) {...}{.raises: [DbError], tags: [].}- Связывает int64 со специфицированным paramIndex. Исходный код Редактировать
proc bindParam(ps: SqlPrepared; paramIdx: int; val: float64) {...}{. raises: [DbError], tags: [].}- Связывает 64-битное число с плавающей точкой со специфицированным paramIndex. Исходный код Редактировать
proc bindParam(ps: SqlPrepared; paramIdx: int; val: string; copy = true) {...}{. raises: [Exception, DbError], tags: [].}- Связывает строку со специфицированным paramIndex. Если copy равно true, то SQLite создаёт свою собственную копию данных сразу Исходный код Редактировать
proc bindParam(ps: SqlPrepared; paramIdx: int; val: openArray[byte]; copy = true) {...}{. raises: [Exception, DbError], tags: [].}- Связывает BLOB со специфицированным paramIndex. Если copy равно true, то SQLite создаёт свою собственную копию данных сразу Исходный код Редактировать
proc bindParam(ps: SqlPrepared; paramIdx: int; val: int) {...}{.raises: [DbError], tags: [].}- Связывает целое число со специфицированным paramIndex. Исходный код Редактировать
proc bindNull(ps: SqlPrepared; paramIdx: int) {...}{.raises: [DbError], tags: [].}- Устанавливает bindparam в указанном paramIndex в значение null (поведение по умолчанию в SQLite). Исходный код Редактировать
proc dbError(db: DbConn) {...}{.noreturn, raises: [DbError], tags: [].}-
Вызывает исключение
DbError.Примеры:
let db = open("mytest.db", "", "", "") if not db.tryExec(sql"SELECT * FROM not_exist_table"): dbError(db) db.close()Исходный код Редактировать proc prepare(db: DbConn; q: string): SqlPrepared {...}{.raises: [DbError], tags: [].}- Создаёт новую
SqlPreparedинструкцию. Исходный код Редактировать proc tryExec(db: DbConn; query: SqlQuery; args: varargs[string, `$`]): bool {...}{. tags: [ReadDbEffect, WriteDbEffect], raises: [].}-
Пытается выполнить запрос и возвращает
trueпри успехе,falseв противном случае.Примеры:
let db = open("mytest.db", "", "", "") if not db.tryExec(sql"SELECT * FROM my_table"): dbError(db) db.close()Исходный код Редактировать proc exec(db: DbConn; query: SqlQuery; args: varargs[string, `$`]) {...}{. tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].}-
Выполняет запрос и вызывает исключение
DbErrorпри неудаче.Примеры:
let db = open("mytest.db", "", "", "") try: db.exec(sql"INSERT INTO my_table (id, name) VALUES (?, ?)", 1, "item#1") except: stderr.writeLine(getCurrentExceptionMsg()) finally: db.close()Исходный код Редактировать proc close(db: DbConn) {...}{.tags: [DbEffect], raises: [DbError].}-
Закрывает подключение к базе данных.
Примеры:
let db = open("mytest.db", "", "", "") db.close()Исходный код Редактировать proc open(connection, user, password, database: string): DbConn {...}{. tags: [DbEffect], raises: [DbError].}-
Открывает подключение к базе данных. Вызывает исключение
DbErrorесли подключение не удалось установить.Примечание: Только параметр
connectionиспользуется дляsqlite.Примеры:
try: let db = open("mytest.db", "", "", "") ## do something... ## db.getAllRows(sql"SELECT * FROM my_table") db.close() except: stderr.writeLine(getCurrentExceptionMsg())Исходный код Редактировать proc unsafeColumnAt(row: InstantRow; index: int32): cstring {...}{.inline, raises: [], tags: [].}-
Возвращает строку cstring для заданного столбца строки.
См. также:
- итератор instantRows пример кода
proc getRow(db: DbConn; query: SqlQuery; args: varargs[string, `$`]): Row {...}{. tags: [ReadDbEffect], raises: [DbError].}-
Извлекает одну строку. Если запрос не возвращает ни одной строки, эта процедура вернёт
Rowсо строками без значений для каждого столбца.Примеры:
let db = open("mytest.db", "", "", "") # Records of my_table: # | id | name | # |----|----------| # | 1 | item#1 | # | 2 | item#2 | doAssert db.getRow(sql"SELECT id, name FROM my_table" ) == Row(@["1", "item#1"]) doAssert db.getRow(sql"SELECT id, name FROM my_table WHERE id = ?", 2) == Row(@["2", "item#2"]) # Returns empty. doAssert db.getRow(sql"INSERT INTO my_table (id, name) VALUES (?, ?)", 3, "item#3") == @[] doAssert db.getRow(sql"DELETE FROM my_table WHERE id = ?", 3) == @[] doAssert db.getRow(sql"UPDATE my_table SET name = 'ITEM#1' WHERE id = ?", 1) == @[] db.close()Исходный код Редактировать proc getAllRows(db: DbConn; query: SqlQuery; args: varargs[string, `$`]): seq[ Row] {...}{.tags: [ReadDbEffect], raises: [DbError].}-
Выполняет запрос и возвращает весь результат набора данных.
Примеры:
let db = open("mytest.db", "", "", "") # Records of my_table: # | id | name | # |----|----------| # | 1 | item#1 | # | 2 | item#2 | doAssert db.getAllRows(sql"SELECT id, name FROM my_table") == @[Row(@["1", "item#1"]), Row(@["2", "item#2"])] db.close()Исходный код Редактировать proc getAllRows(db: DbConn; stmtName: SqlPrepared): seq[Row] {...}{. tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].}- Исходный код Редактировать
proc getValue(db: DbConn; query: SqlQuery; args: varargs[string, `$`]): string {...}{. tags: [ReadDbEffect], raises: [DbError].}-
Выполняет запрос и возвращает первый столбец первой строки набора данных результатов. Возвращает
""если набор данных не содержит строк или значение в базе данных —NULL.Примеры:
let db = open("mytest.db", "", "", "") # Records of my_table: # | id | name | # |----|----------| # | 1 | item#1 | # | 2 | item#2 | doAssert db.getValue(sql"SELECT name FROM my_table WHERE id = ?", 2) == "item#2" doAssert db.getValue(sql"SELECT id, name FROM my_table") == "1" doAssert db.getValue(sql"SELECT name, id FROM my_table") == "item#1" db.close()Исходный код Редактировать proc getValue(db: DbConn; stmtName: SqlPrepared): string {...}{. tags: [ReadDbEffect, WriteDbEffect], raises: [].}- Исходный код Редактировать
proc tryInsertID(db: DbConn; query: SqlQuery; args: varargs[string, `$`]): int64 {...}{. tags: [WriteDbEffect], raises: [].}-
Выполняет запрос (обычно «INSERT») и возвращает сгенерированный идентификатор строки или -1 в случае ошибки.
Примеры:
let db = open("mytest.db", "", "", "") db.exec(sql"CREATE TABLE my_table (id INTEGER, name VARCHAR(50) NOT NULL)") doAssert db.tryInsertID(sql"INSERT INTO not_exist_table (id, name) VALUES (?, ?)", 1, "item#1") == -1 db.close()Исходный код Редактировать proc insertID(db: DbConn; query: SqlQuery; args: varargs[string, `$`]): int64 {...}{. tags: [WriteDbEffect], raises: [DbError].}-
Выполняет запрос (обычно «INSERT») и возвращает сгенерированный идентификатор строки.
Вызывает исключение
DbErrorпри неудачной вставке строки. Для Postgre это добавляетRETURNING idв запрос, поэтому работает только если ваш первичный ключ названid.Примеры:
let db = open("mytest.db", "", "", "") db.exec(sql"CREATE TABLE my_table (id INTEGER, name VARCHAR(50) NOT NULL)") for i in 0..2: let id = db.insertID(sql"INSERT INTO my_table (id, name) VALUES (?, ?)", i, "item#" & $i) echo "LoopIndex = ", i, ", InsertID = ", id # Output: # LoopIndex = 0, InsertID = 1 # LoopIndex = 1, InsertID = 2 # LoopIndex = 2, InsertID = 3 db.close()Исходный код Редактировать proc tryInsert(db: DbConn; query: SqlQuery; pkName: string; args: varargs[string, `$`]): int64 {...}{.tags: [WriteDbEffect], raises: [].}- то же самое, что и tryInsertID Исходный код Редактировать
proc insert(db: DbConn; query: SqlQuery; pkName: string; args: varargs[string, `$`]): int64 {...}{.tags: [WriteDbEffect], raises: [DbError].}- то же самое, что и insertId Исходный код Редактировать
proc execAffectedRows(db: DbConn; query: SqlQuery; args: varargs[string, `$`]): int64 {...}{. tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].}-
Выполняет запрос (обычно «UPDATE») и возвращает количество затронутых строк.
Примеры:
let db = open("mytest.db", "", "", "") # Records of my_table: # | id | name | # |----|----------| # | 1 | item#1 | # | 2 | item#2 | doAssert db.execAffectedRows(sql"UPDATE my_table SET name = 'TEST'") == 2 db.close()Исходный код Редактировать proc execAffectedRows(db: DbConn; stmtName: SqlPrepared): int64 {...}{. tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].}- Исходный код Редактировать
proc setEncoding(connection: DbConn; encoding: string): bool {...}{.tags: [DbEffect], raises: [DbError].}
-
Устанавливает кодировку подключения к базе данных, возвращает
trueпри успехе иfalseпри ошибке.Примечание: Кодировку нельзя изменить после её установки. Согласно документации SQLite3, любая попытка изменить кодировку после создания базы данных будет проигнорирована.
Исходный код Изменить
Итераторы
iterator fastRows(db: DbConn; query: SqlQuery; args: varargs[string, `$`]): Row {...}{. tags: [ReadDbEffect], raises: [DbError, DbError].}-
Выполняет запрос и итерирует по результатам.
Этот метод очень быстрый, но потенциально опасный. Используйте этот итератор только если вам нужны ВСЕ строки.
Примечание: Прерывание итератора
fastRows()во время цикла приведёт к тому, что следующий запрос к базе данных вызовет исключениеDbErrorunable to close due to ....Примеры:
let db = open("mytest.db", "", "", "") # Records of my_table: # | id | name | # |----|----------| # | 1 | item#1 | # | 2 | item#2 | for row in db.fastRows(sql"SELECT id, name FROM my_table"): echo row # Output: # @["1", "item#1"] # @["2", "item#2"] db.close()Исходный код Изменить iterator fastRows(db: DbConn; stmtName: SqlPrepared): Row {...}{. tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].}- Исходный код Изменить
iterator instantRows(db: DbConn; query: SqlQuery; args: varargs[string, `$`]): InstantRow {...}{. tags: [ReadDbEffect], raises: [DbError, DbError].}-
Аналогичен итератору fastRows, но возвращает дескриптор, который может быть использован для получения текста столбцов по требованию с помощью
[]. Возвращённый дескриптор действителен только внутри тела итератора.Примеры:
let db = open("mytest.db", "", "", "") # Records of my_table: # | id | name | # |----|----------| # | 1 | item#1 | # | 2 | item#2 | for row in db.instantRows(sql"SELECT * FROM my_table"): echo "id:" & row[0] echo "name:" & row[1] echo "length:" & $len(row) # Output: # id:1 # name:item#1 # length:2 # id:2 # name:item#2 # length:2 db.close()Исходный код Изменить iterator instantRows(db: DbConn; stmtName: SqlPrepared): InstantRow {...}{. tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].}- Исходный код Изменить
iterator instantRows(db: DbConn; columns: var DbColumns; query: SqlQuery; args: varargs[string, `$`]): InstantRow {...}{. tags: [ReadDbEffect], raises: [DbError, DbError].}-
Аналогичен итератору instantRows, но устанавливает информацию о столбцах в
columns.Примеры:
let db = open("mytest.db", "", "", "") # Records of my_table: # | id | name | # |----|----------| # | 1 | item#1 | # | 2 | item#2 | var columns: DbColumns for row in db.instantRows(columns, sql"SELECT * FROM my_table"): discard echo columns[0] # Output: # (name: "id", tableName: "my_table", typ: (kind: dbNull, # notNull: false, name: "INTEGER", size: 0, maxReprLen: 0, precision: 0, # scale: 0, min: 0, max: 0, validValues: @[]), primaryKey: false, # foreignKey: false) db.close()Исходный код Изменить iterator rows(db: DbConn; query: SqlQuery; args: varargs[string, `$`]): Row {...}{. tags: [ReadDbEffect], raises: [DbError].}-
Аналогичен итератору fastRows, но медленнее и безопаснее.
Примеры:
let db = open("mytest.db", "", "", "") # Records of my_table: # | id | name | # |----|----------| # | 1 | item#1 | # | 2 | item#2 | for row in db.rows(sql"SELECT id, name FROM my_table"): echo row ## Output: ## @["1", "item#1"] ## @["2", "item#2"] db.close()Исходный код Изменить iterator rows(db: DbConn; stmtName: SqlPrepared): Row {...}{. tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].}- Исходный код Изменить
Макросы
macro bindParams(ps: SqlPrepared; params: varargs[untyped]): untyped
- Исходный код Изменить
Шаблоны
template dbBindParamError(paramIdx: int; val: varargs[untyped])
- Вызывает исключение
DbError. Исходный код Изменить template exec(db: DbConn; stmtName: SqlPrepared; args: varargs[typed]): untyped
- Исходный код Изменить
Экспорт
- DbTypeKind, sql, DbType, SqlQuery, DbColumn, ReadDbEffect, DbError, WriteDbEffect, dbError, DbColumns, DbEffect
© 2006–2021 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/db_sqlite.html