Android 使用 RANK() 创建视图时出现 SQLite 语法错误
Android SQLite Syntax Error creating a view with RANK()
我正在尝试使用 RANK() window 函数在 SQLite 中创建一个视图。当我执行以下代码时:
val txt = "CREATE VIEW VW_CAPITULOS_ORDER AS\n" +
" SELECT id_libro, capitulo,\n" +
" RANK() OVER (\n" +
" ORDER BY id_libro, CAST(SUBSTR(capitulo, 1, INSTR(capitulo||' ', ' ')) AS INTEGER)\n" +
" ) ranking\n" +
" FROM tbl_capitulos;\n"
db.execSQL(txt)
并且在运行时我收到以下异常:
*E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.systango.bibliacatolica, PID: 20837
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.systango.bibliacatolica/com.systango.bibliacatolica.MainActivity}: android.database.sqlite.SQLiteException: near "(": syntax error (Sqlite code 1 SQLITE_ERROR): , while compiling: CREATE VIEW VW_CAPITULOS_ORDER AS
SELECT id_libro, capitulo,
RANK() OVER (
ORDER BY id_libro, CAST(SUBSTR(capitulo, 1, INSTR(capitulo||' ', ' ')) AS INTEGER)
) ranking
FROM tbl_capitulos;, (OS error - 11:Try again)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3897)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4076)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2473)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:219)
at android.app.ActivityThread.main(ActivityThread.java:8349)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)
Caused by: android.database.sqlite.SQLiteException: near "(": syntax error (Sqlite code 1 SQLITE_ERROR): , while compiling: CREATE VIEW VW_CAPITULOS_ORDER AS
SELECT id_libro, capitulo,
RANK() OVER (
ORDER BY id_libro, CAST(SUBSTR(capitulo, 1, INSTR(capitulo||' ', ' ')) AS INTEGER)
) ranking
FROM tbl_capitulos;, (OS error - 11:Try again)
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1030)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:637)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:610)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:66)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:33)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1899)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1817)*
我怀疑这是 Android 中存在的 SQLite 版本的问题(已在 Huawei P40 Lite 上检查版本 3.22)或类似问题。 SQLite 文档说 window 函数出现在版本 3.25 (https://sqlite.org/windowfunctions.html) 中。此脚本在 DB Browser for SQLite
应用程序中执行没有问题。存在一种使用新版本 SQLite 的方法,即 phone?
附带的版本
您的应用无法更改 phone.
的 SQLite 版本
作为解决方法,您可以使用相关子查询来模仿 window 函数 RANK()
:
的功能
CREATE VIEW VW_CAPITULOS_ORDER AS
SELECT c.id_libro, c.capitulo,
(
SELECT COUNT(*) FROM tbl_capitulos
WHERE id_libro < c.id_libro
OR (id_libro = c.id_libro AND (capitulo + 0) < (c.capitulo + 0))
) + 1 ranking
FROM tbl_capitulos c;
请注意,您无需将 capitulo
的子字符串提取到第一个 ' '
即可将其转换为整数。
您可以通过添加 0
.
来进行隐式转换
我正在尝试使用 RANK() window 函数在 SQLite 中创建一个视图。当我执行以下代码时:
val txt = "CREATE VIEW VW_CAPITULOS_ORDER AS\n" +
" SELECT id_libro, capitulo,\n" +
" RANK() OVER (\n" +
" ORDER BY id_libro, CAST(SUBSTR(capitulo, 1, INSTR(capitulo||' ', ' ')) AS INTEGER)\n" +
" ) ranking\n" +
" FROM tbl_capitulos;\n"
db.execSQL(txt)
并且在运行时我收到以下异常:
*E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.systango.bibliacatolica, PID: 20837
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.systango.bibliacatolica/com.systango.bibliacatolica.MainActivity}: android.database.sqlite.SQLiteException: near "(": syntax error (Sqlite code 1 SQLITE_ERROR): , while compiling: CREATE VIEW VW_CAPITULOS_ORDER AS
SELECT id_libro, capitulo,
RANK() OVER (
ORDER BY id_libro, CAST(SUBSTR(capitulo, 1, INSTR(capitulo||' ', ' ')) AS INTEGER)
) ranking
FROM tbl_capitulos;, (OS error - 11:Try again)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3897)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4076)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2473)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:219)
at android.app.ActivityThread.main(ActivityThread.java:8349)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)
Caused by: android.database.sqlite.SQLiteException: near "(": syntax error (Sqlite code 1 SQLITE_ERROR): , while compiling: CREATE VIEW VW_CAPITULOS_ORDER AS
SELECT id_libro, capitulo,
RANK() OVER (
ORDER BY id_libro, CAST(SUBSTR(capitulo, 1, INSTR(capitulo||' ', ' ')) AS INTEGER)
) ranking
FROM tbl_capitulos;, (OS error - 11:Try again)
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1030)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:637)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:610)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:66)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:33)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1899)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1817)*
我怀疑这是 Android 中存在的 SQLite 版本的问题(已在 Huawei P40 Lite 上检查版本 3.22)或类似问题。 SQLite 文档说 window 函数出现在版本 3.25 (https://sqlite.org/windowfunctions.html) 中。此脚本在 DB Browser for SQLite
应用程序中执行没有问题。存在一种使用新版本 SQLite 的方法,即 phone?
您的应用无法更改 phone.
的 SQLite 版本
作为解决方法,您可以使用相关子查询来模仿 window 函数 RANK()
:
CREATE VIEW VW_CAPITULOS_ORDER AS
SELECT c.id_libro, c.capitulo,
(
SELECT COUNT(*) FROM tbl_capitulos
WHERE id_libro < c.id_libro
OR (id_libro = c.id_libro AND (capitulo + 0) < (c.capitulo + 0))
) + 1 ranking
FROM tbl_capitulos c;
请注意,您无需将 capitulo
的子字符串提取到第一个 ' '
即可将其转换为整数。
您可以通过添加 0
.