Обновление SQLlite3 не имеет никакого эффекта - PullRequest
0 голосов
/ 08 июля 2011

Я не эксперт по SQL, но у меня есть ошибка в приложении для iPhone, когда оператор UPDATE не влияет на БД.Я использовал плагин менеджера SQLlite для FireFox, чтобы попробовать dbug, многократно внося поправки и выполняя UPDATE на БД.Я также тщательно проверил заявление и SQL Validator, который сказал, что он соответствует базовому стандарту SQL.

Можете ли вы заметить что-то не так с приведенным ниже утверждением?

UPDATE sections
SET
    title = 'What is acne ? ABC',
    text = 'Pus on your face',
    created = '2010-03-10 18:46:55',
    modified = '2011-07-04 17:38:44',
    position = 1,
    condition_id = 4
WHERE id = 10;

Ответы [ 3 ]

2 голосов
/ 12 июля 2011

Существует некоторая путаница и непоследовательность в том, как SQLite и различные реализации Mozilla, Google, Adobe и других обрабатывают числовые первичные ключи в базах данных, таблицы которых были созданы вне этих реализаций, и где первичные ключи были определены как целое число.тип, но не как «INTEGER» [дословно] - то есть они были определены как INT или INT16 или INT32 и т. д.

        INTEGER PRIMARY KEY in mothership SQLite is an alias for the rowid.
        INT PRIMARY KEY in mothership SQLite is not an alias for the rowid.

Член консорциума (или любой разработчик) может или не может следовать этому правилу,(SQLite находится в свободном доступе, конечно.)

См. Раздел 2.0 здесь: http://www.sqlite.org/datatypes.html

и см. Раздел по RowId и первичному ключу здесь: http://www.sqlite.org/lang_createtable.html#rowid

Столбец PRIMARY KEY становится целочисленным первичным ключом только в том случае, если объявленное имя типа является точно "INTEGER".Другие имена целочисленных типов, такие как «INT», «BIGINT», «SHORT INTEGER» или «UNSIGNED INTEGER», заставляют столбец первичного ключа вести себя как обычный столбец таблицы с целочисленным сходством и уникальным индексом, не как псевдоним дляrowid .[выделение добавлено]

Разработчик, который не следует правилу, возможно, даже не подозревал, что он нарушает правило, так как это правило "запятнанного".В любом случае, это означает, что на практике одна реализация может обрабатывать предоставленное значение как псевдоним для rowid, а другая реализация - нет.Если задано значение 10, можно получить кортеж, у которого rowid = 10, а можно получить кортеж, где значение указанного столбца = 10. Это, конечно, приводит к ложным результатам в запросах, и они могут выглядеть очень хорошо иправдоподобные результаты, но они совершенно неверны.

Рассмотрим следующий простой тест: с использованием основных утилит SQLite, а не предоставляемых одним из разработчиков, выполняются следующие операторы DDL и DML;затем в своей реализации откройте базу данных и снова выполните операторы DML, чтобы сравнить результаты DML:

        CREATE TABLE TEST
        ("id" INT PRIMARY KEY, "name" text)  -- ** NOTE "INT" not "INTEGER"

        INSERT INTO TEST
        (id, name)
        VALUES
        (7,'seven')


         ** *** N.B. THE ROWID OF THE ROW INSERTED ABOVE =  1  *** **


        select rowid, id, name from test

       result:  1 | 7 | seven


        select * from TEST 

        result:  7 | seven


        select * from TEST where id = 7

        result:  ?????  [ymmv]



        select * from TEST where id = 1


        result: ?????  [ymmv]

В зависимости от того, как конкретная реализация обрабатывает первичный ключ INT, третий оператор выбора выше (выберите * изTEST, где id = 7) может возвращать одну строку или может ничего не возвращать!

Если реализация рассматривает INT PK как псевдоним для идентификатора строки, ну, нет строки, чьяrowid = 7, и поэтому он ничего не вернет.Если реализация рассматривает INT PK как обычное значение, она найдет строку.

Теперь, если бы вы вставили больше строк в таблицу TEST, вы в конечном итоге создали бы строку, у которой rowid = 7. В одномиз этих своенравных реализаций, когда вы используете это предложение where - , где id = 7 --- вы можете подумать, что обращаетесь к кортежу с id = 7, но на самом деле вы обращаетесь к кортежу, чейROWID = 7.Вы могли бы получить неправильный кортеж и не могли бы этого понять.Рассмотрим возможности при присоединении дочерней таблицы к родительской таблице: дочерняя таблица содержит значение внешнего ключа, равное 7. Какой кортеж возвращает внутреннее соединение из родительской таблицы?Это зависит от того, учитывает ли реализация различие между первичными ключами INT и INTEGER.

В прошлом году я тщательно задокументировал это для Adobe AIR, BTW, а также сообщил об этом в группе новостей SQLite.Возможно, что некоторые реализации за это время изменили поведение.

При создании таблиц SQLite лучше всего использовать INTEGER [дословно] для первичных ключей, а не другие распознаваемые типы int.

0 голосов
/ 08 июля 2011

Единственная вещь в запросе, которая кажется мне достойной дальнейшего изучения, это вопросительный знак в значении для [title]Удалите его и посмотрите, изменит ли это что-нибудь.Возможно, он где-то неправильно анализируется в качестве заполнителя параметра.

0 голосов
/ 08 июля 2011

Если ваш запрос правильный, то вам нужно убедиться в двух вещах.

  1. Вы написали finalize_statement, как это?

    sqlite3_finalize(selectStatement);
    

2. Если вы тестируете в симуляторе.Вы уверены, что проверяете обновление базы данных по следующему пути?

/user/Libary/Application Support/iPhone Simulator/Your_Version_Number/Applications/YOUR_APPLICATION_GUID/Documents

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...