Spec-Zone.ru › Nim 1

db_sqlite

Обёртка для базы данных SQLite более высокого уровня. Этот интерфейс реализован и для других баз данных.

Основное использование

Основной порядок использования этого модуля:

  1. Открыть соединение с базой данных
  2. Выполнить SQL-запрос
  3. Закрыть соединение с базой данных

Подстановка параметров

Все модули 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].

Обоснование:

  1. Это близко к тому, что многие БД предлагают напрямую (char**)
  2. Это скрывает количество поддерживаемых типов БД

(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() во время цикла приведёт к тому, что следующий запрос к базе данных вызовет исключение DbError unable 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API