(21)用NULL预处理语句调用API

问题描述 投票:1回答:2

我目前正在使用sqlite数据库,android。我想将包含sql语句的原始文件导入到我的数据库中。我的方案如下。

  1. 将原始文件读为字符串
  2. ;符号拆分那些sql语句
  3. 在循环内执行每个语句

但是当我执行sql语句时,它只会在执行文件的一行后抛出(21) API called with NULL prepared statement(21) misuse at line 70084 of [b3bb660af9]等错误。我的编码没有任何问题。

错误日志

03-08 14:56:41.652 15867-15867/com.sv.gauge D/EXECUTED SQL: PRAGMA foreign_keys=OFF
03-08 14:56:41.662 15867-15867/com.sv.gauge E/SQLiteLog: (21) API called with NULL prepared statement
03-08 14:56:41.662 15867-15867/com.sv.gauge E/SQLiteLog: (21) misuse at line 70084 of [b3bb660af9]
03-08 14:56:41.672 15867-15867/com.sv.gauge D/AndroidRuntime: Shutting down VM
03-08 14:56:41.672 15867-15867/com.sv.gauge E/AndroidRuntime: FATAL EXCEPTION: main
                                                          Process: com.sv.gauge, PID: 15867
                                                          java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sv.gauge/com.sv.gauge.LoginActivity}: android.database.sqlite.SQLiteException: not an error (code 0)
                                                          #################################################################
                                                          Error Code : 0 (SQLITE_OK)
                                                          Caused By : not an error (code 0)
                                                          #################################################################
                                                              at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2695)
                                                              at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2769)
                                                              at android.app.ActivityThread.access$900(ActivityThread.java:177)
                                                              at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1430)
                                                              at android.os.Handler.dispatchMessage(Handler.java:102)
                                                              at android.os.Looper.loop(Looper.java:135)
                                                              at android.app.ActivityThread.main(ActivityThread.java:5910)
                                                              at java.lang.reflect.Method.invoke(Native Method)
                                                              at java.lang.reflect.Method.invoke(Method.java:372)
                                                              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)
                                                           Caused by: android.database.sqlite.SQLiteException: not an error (code 0)
                                                          #################################################################
                                                          Error Code : 0 (SQLITE_OK)
                                                          Caused By : not an error (code 0)
                                                          #################################################################
                                                              at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method)
                                                              at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:904)
                                                              at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754)
                                                              at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
                                                              at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1814)
                                                              at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1743)
                                                              at com.sv.gauge.controller.GaugeDatabaseHelper.onCreate(GaugeDatabaseHelper.java:78)
                                                              at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:251)
                                                              at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
                                                              at com.sv.gauge.controller.GaugeDatabaseHelper.getReadableDatabase(GaugeDatabaseHelper.java:43)
                                                              at com.sv.gauge.controller.GaugeDatabaseHelper.<init>(GaugeDatabaseHelper.java:37)
                                                              at com.sv.gauge.LoginActivity.onCreate(LoginActivity.java:39)
                                                              at android.app.Activity.performCreate(Activity.java:6178)
                                                              at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                                                              at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2648)
                                                                ... 10 more

用于导入原始sql文件的代码段

@Override
public void onCreate(SQLiteDatabase db) {
    InputStream inputStream = context.getResources().openRawResource(R.raw.database);
    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    String line;

    StringBuilder builder = new StringBuilder();
    try {
        while ((line = reader.readLine()) != null) {
            builder.append(line);
            builder.append(System.getProperty("line.separator"));
        }
        String rawSql = builder.toString();

        String[] sqls = rawSql.split(";");
        for (String sql : sqls) {
            db.execSQL(sql);
            Log.d("EXECUTED SQL", sql);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

包含sql语句的原始文件

PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE "domain" (
    `id`    INTEGER PRIMARY KEY AUTOINCREMENT,
    `title` TEXT NOT NULL,
    `description`   TEXT NOT NULL,
    `first_step`    INTEGER NOT NULL
);
INSERT INTO "domain" VALUES(1,'GENERATOR ROOM','take measurements of generator room',1);
CREATE TABLE "domain_step" (
    `id`    INTEGER PRIMARY KEY AUTOINCREMENT,
    `domain_id` INTEGER NOT NULL,
    `title` TEXT NOT NULL,
    `visual_type`   TEXT NOT NULL,
    `visual_link`   TEXT,
    `visual_description`    TEXT NOT NULL,
    `next_step` INTEGER,
    `show_map`  INTEGER NOT NULL,
    `last_step` INTEGER NOT NULL,
    `map_from_previous_link`    TEXT,
    `enable_skip`   INTEGER NOT NULL,
    `skip_to_step`  INTEGER,
    `map_from_beginning_link`   TEXT,
    `value_type`    TEXT NOT NULL,
    `value_hint`    TEXT,
    `default_value` TEXT,
    `default_from_value`    TEXT,
    `default_to_value`  TEXT,
    `report_description`    TEXT
);
INSERT INTO "domain_step" VALUES(1,1,'Safty Items','IMAGE',NULL,'Did you ware safety Items?

1) Ear protection

2) Helmet with light',2,0,0,NULL,0,NULL,NULL,'NONE',NULL,NULL,NULL,NULL,NULL);
COMMIT;
android database sqlite android-sqlite batch-processing
2个回答
1
投票

如果sql文件已经有“;”然后

try {
    while ((line = reader.readLine()) != null) {
        builder.append(line);
        builder.append(System.getProperty("line.separator"));
    }

应该

try {
    while ((line = reader.readLine()) != null) {
        builder.append(line);
    }

0
投票

其他访客的另一种选择

我得到了这一行,因为我的SQL脚本中有一个以;字符结尾的注释。因此,它试图单独执行注释,从而产生“NULL prepared statement”错误。

-- version 1 of the database vocab table was
--
-- CREATE TABLE vocab
-- ( _id INTEGER PRIMARY KEY,
--   date INTEGER,
--   list_id TEXT NOT NULL, -- this should have been INTEGER
--   mongol TEXT NOT NULL,
--   definition TEXT,
--   pronunciation TEXT,
--   audio TEXT,
--   FOREIGN KEY(list_id) REFERENCES lists(_id)
-- );

PRAGMA foreign_keys=off;

BEGIN TRANSACTION;

ALTER TABLE vocab RENAME TO _vocab_old;

...

解决方案

您可以通过执行以下任一操作来解决此问题:

  1. 删除以;结尾的注释行
  2. ;之后添加额外的文本。我这样做了: -- version 1 of the database vocab table was -- -- CREATE TABLE vocab -- ( _id INTEGER PRIMARY KEY, -- date INTEGER, -- list_id TEXT NOT NULL, -- this should have been INTEGER -- mongol TEXT NOT NULL, -- definition TEXT, -- pronunciation TEXT, -- audio TEXT, -- FOREIGN KEY(list_id) REFERENCES lists(_id) -- ); -- end comment (comment lines cannot end with semicolon)
  3. 更改运行脚本的逻辑,以便它忽略以--开头并且不尝试运行它们的任何行。

结论

如果您收到此错误,请查找可能单独执行的迷路;字符。

© www.soinside.com 2019 - 2024. All rights reserved.