SQLITE какие ограниченные символы для идентификаторов

Я пытаюсь создать систему, в которой параметры SQL автоматически привязываются к новым запросам. Согласно этой теме:

SQL Server - недопустимые символы в именах параметров

Внутри идентификаторов должны быть разрешены символы @, _ и #. Итак, я попытался построить параметры как:

: tablename # fieldname

Но при этом я получаю ошибку:

PBdatabase.select_query: [1] DB [2] prepare () SELECT * FROM creature WHERE pk =: creature # pk [рядом с "#pk": синтаксическая ошибка]

Кажется, ему не нравится символ #, я пробовал использовать подчеркивание, похоже, он работает, но я уже использую подчеркивание в именах полей. Вот почему я хотел использовать другого персонажа.

Поскольку в приведенном выше потоке говорилось о SQL-сервере, ограниченные символы в SQLITE могут быть другими. Я нашел список ограниченных ключевых слов SQLITE, но не символов.

Кто-нибудь знает, какой еще специальный символ я мог бы использовать?


Обновлять

Кто-нибудь хочет знать, какая у меня от этого польза. Вот пример, допустим, у вас есть 2 таблицы с отношением 1 к N: Флот содержит корабли.

Вы хотите отобразить форму, состоящую из 2 блоков, где в верхней части отображается 1 выбранный флот в данный момент. Где в нижнем блоке перечислены все корабли во флоте.

Первый запрос блока будет примерно таким:

SELECT pk, number, location  FROM fleet;

Затем поля выбранной записи будут помещены в реестр полей со следующими именами (при условии, что символ # будет действительным):

:fleet#pk
:fleet#number
:fleet#location

Затем будет запущен второй запрос для второго блока, включая зарегистрированные поля выше. Таким образом, запрос будет выглядеть так:

SELECT pk, fk_fleet, name  FROM ship WHERE fk_fleet = :fleet#pk

В этом запросе используется параметр из запроса выше. Идентификатор будет заменен значением из предыдущего запроса. Это позволяет отображать только корабли, связанные с выбранным выше флотом, вместо всех доступных кораблей.

Некоторые из вас могут сказать, что я могу просто сохранить нужные мне переменные и передать их в качестве параметра следующему запросу. Проблема в том, что все запросы загружаются из базы данных. На самом деле я не знаю, какой запрос я собираюсь запустить и какое значение мне нужно будет сохранить для другого запроса. Вместо этого я сохраняю их все в реестре, и если другой оператор SQL запросит параметр, значение будет доступно.


person larienna    schedule 03.08.2015    source источник
comment
документация: sqlite.org/lang_keywords.html   -  person njzk2    schedule 03.08.2015
comment
кстати, я не понимаю, что вы пытаетесь сделать. ваша система привязки должна произойти до того, как запрос будет фактически оценен, поэтому достоверность выражения не имеет значения   -  person njzk2    schedule 03.08.2015
comment
На странице lang_keyword перечислены ключевые слова, а не символы. Что касается того, что я хочу сделать, это разрешить обмен данными между запросами. Я обновлю сообщение и пример.   -  person larienna    schedule 04.08.2015
comment
любопытнее и любопытнее. что такое реестр полей?   -  person njzk2    schedule 04.08.2015
comment
Это ArrayMap, состоящий из имени поля в качестве ключа и значения поля, сохраненного в виде строки. Перед выполнением запроса я прохожу через ArrayMap и проверяю, используется ли ключ в запросе, если да, я привязываю значение к оператору (привязка неподписанного параметра вызывает ошибку, поэтому я не могу связать все). Реестр полей - мое изобретение, не уверен, что есть лучшее решение, но найти его немного сложно. Если вы так увлечены этим, я могу опубликовать образец кода.   -  person larienna    schedule 05.08.2015
comment
В намерении использовать следующее соглашение об именах: fieldnameOFtable, например: numberOFfleet. Поэтому я использую заглавную букву оператора OF (также можно использовать IN), что позволяет использовать только буквенно-цифровые символы.   -  person larienna    schedule 05.08.2015
comment
Возможный дубликат SQL Server - недопустимые символы в именах параметров   -  person    schedule 07.11.2017


Ответы (2)


SQLite и SQL-сервер похожи, но имеют немного другой синтаксис, как и все реализации SQL обычно имеют разные правила.

SQLite позволяет использовать буквы _1 _-_ 2_, _3 _-_ 4_, _5 _-_ 6_, _, $, пары двоеточий "::" после первого символа и символ Unicode, размер которого превышает u007f.

Кроме того, в конце параметра можно добавить круглые скобки: ( и ), между которыми может быть любой символ, кроме символов пробела ASCII и символа ). 0x00 также никогда не допускается (поскольку это означает конец C-строки).

Примеры

Итак, допустимы следующие параметры:

:a, :_, :$, :a::, :A, :9, :????, :  (U + 2000, символ Юникода с четырьмя пробелами), :a(:/$asd().

Хотя они недействительны:

:#, :::, ::, :;, :(, :( ) (нормальное пространство ASCII)

Источник

Я нашел статью на веб-сайте SQLite (см. https://www.sqlite.org/draft/tokenreq.html), в котором указано, что именованные параметры (также известные как переменные) могут состоять из:

Имя параметра определяется как последовательность из одного или нескольких символов, состоящих из БУКВЕННО-ЦИФРОВЫХ символов и / или знаков доллара (u0025), смешанных с парами двоеточий (u003a) и, необязательно, за которыми следует любая последовательность ненулевых, отличных от WHITESPACE. символы в круглых скобках (u0028 и u0029).

где БУКВЕННО-ЦИФРОВЫЙ символ определяется как:

АЛФАВИТНЫЙ Любой из символов в диапазоне от u0041 до u005a (буквы от A до Z) или в диапазоне от u0061 до u007a (буквы от a до z), или символ u005f (_), или любой другой символ, больший, чем u007f.

и

ЦИФРОВОЙ Любой из символов в диапазоне от u0030 до u0039 (цифры от 0 до 9).

Я также написал короткий скрипт Python для подтверждения приведенных выше значений. Символы Юникода с 0xd800 по 0xdfff также не работали из-за отказа Python3 создавать строку с этими значениями (см. https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF, чтобы узнать почему), так что это может работать в коде SQLite C.

import sqlite3
import tqdm
import itertools

with sqlite3.connect(":memory:") as conn:
    with conn as cur:
        cur.execute("create table test(x);")

        strings_to_test = ["{}", "a{}", "{0}{0}", "a{0}{0}", "a({})"]
        # make a list to hold the invalid chars for each test item
        strings_to_test = {x: list() for x in strings_to_test}

        def attempt_insert(string, i, invalid_list):
            try:
                cur.execute("insert into test values ( :{} );".format(string)
                    .format(chr(i)),{"{}".format(string).format(chr(i)): 42})
            except Exception as e:
                invalid_list.append(i)
        
        # 0x10FFFF is the max value for UTF chars
        for char_num in tqdm.trange(0, 0x10FFFF):
            for string, invalid_char_list in strings_to_test.items():
                attempt_insert(string, char_num, invalid_char_list)

def gen_ranges(i):
    # from https://stackoverflow.com/a/4629241 with changes for Python3
    for a, b in itertools.groupby(enumerate(i), lambda x: x[1] - x[0]):
        b = list(b)
        yield b[0][1], b[-1][1]

def ranges(invalid_chars):
    return "{}".format(["0x{:06x} to 0x{:06x}".format(*range) \
        for range in gen_ranges(invalid_chars)])

print("Invalid Single Chars: ie :x were:                 {}".format(
    ranges(strings_to_test["{}"])))
print("Invalid Single Second Chars: ie :ax were:         {}".format(
    ranges(strings_to_test["a{}"])))
print("Invalid Double Chars: ie :xx were: {}".format(
    ranges(strings_to_test["{0}{0}"])))
print("Invalid Double Chars in second pos: ie :axx were: {}".format(
    ranges(strings_to_test["a{0}{0}"])))
print("Invalid Parenthesised Chars: ie :abc(x) were:     {}".format(
    ranges(strings_to_test["a({})"])))
person Alois Klink    schedule 28.07.2018

В SQLite имена параметров запроса могут содержать только буквенно-цифровые символы (за исключением ?NNN, которое должно быть целым числом); см. второй абзац справочника по функции sqlite3_bind_*.

person Colonel Thirty Two    schedule 03.08.2015
comment
Если бы принимались только буквенно-цифровые символы, подчеркивание было бы недопустимым символом, но это не так. Существуют ли другие допустимые не буквенно-цифровые символы, кроме подчеркивания? - person larienna; 04.08.2015
comment
Кажется, что в некоторых случаях подчеркивание может быть буквенно-цифровым символом. Возможно, это случай SQLITE. Если это так, я буду придерживаться подчеркивания, некрасиво, но это работает. - person larienna; 04.08.2015