【问题标题】:How to split comma-separated value in SQLite?如何在 SQLite 中拆分逗号分隔值?
【发布时间】:2014-08-07 04:11:26
【问题描述】:

我想在 SQLite 数据库中拆分逗号分隔的String

示例:我的表 1 中有一个 Category 列。

|Category                      |
|------------------------------|
|Auto,A,1234444                |
|Auto,B,2345444                |
|Electronincs,Computer,33443434|

我只想从上面的字符串中获取一个值。

value1: Auto
value2: A
value3: 1234444

我在 Google 上搜索了很多;我找到了一种使用Replace()Trim() 替换逗号的方法。但是,我想获得一种更简单的方法。

在 SQL 中,提供SubString()。但是在 SQLite 中,没有这样的功能。如何解决?

编辑:我检查了substr()。但是,这个函数可以设置最大长度来获取字符串值,而我的字符串值没有固定长度。

【问题讨论】:

  • @dipali 是否可以先获取整个String,然后用Java 处理它? (使用String.split(",")
  • @AndrewT。这是不可能的。我的查询还不够。我已经创建了 10 行查询,我只是把这个问题解决方案放在那里..请帮助我。

标签: android sql sqlite


【解决方案1】:

您可以使用公共表表达式在 SQLite 中拆分逗号分隔的值。

WITH split(word, str) AS (
    -- alternatively put your query here
    -- SELECT '', category||',' FROM categories
    SELECT '', 'Auto,A,1234444'||','
    UNION ALL SELECT
    substr(str, 0, instr(str, ',')),
    substr(str, instr(str, ',')+1)
    FROM split WHERE str!=''
) SELECT word FROM split WHERE word!='';

输出如预期:

Auto
A
1234444

【讨论】:

  • 如何修改此查询以在名称具有逗号分隔值的CREATE TABLE tablename (id INT,name VARCHAR(20)); 等简单表上工作?
  • @indago:创建一个选择 id 和拆分名称的视图?这是你的意思吗?
  • 字符串中只有一项时有问题,例如trim('Auto', ','),没有输出。
  • 我们可以将substr部分修改为substr(str, 0, case when instr(str, ',') then instr(str, ',') else length(str)+1 end),以便打印不带逗号分隔符的字符串。
  • 如何在选择后的列上使用它?
【解决方案2】:

SQLite 为此提供了函数,例如获取子字符串substr('your string', start_position, end_position),获取特定字符在字符串instr('22:string', ':') 中的位置,以及获取字符串的长度length('string')。 现在让我们看看下面的例子:

select substr('22:khan', x, y);
returns a string starting at x and ends with y;
select substr('22:khan', 0, instr('22:khan',':'));
returns: 22 
select substr('22:khan', instr('22:khan',':')+1, length('22:khan'));
returns: khan
select substr('22:khan',instr('22:khan',':'), length('22:khan'));
returns: :khan
select substr('Noor,Khan', 0, instr('Noor,Khan', ','));
returns: Noor
select substr('Noor,Khan', instr('Noor,Khan', ',')+1, length('Noor,Khan'));
returns: Khan

欲了解更多信息,请访问:https://www.sqlite.org/lang_corefunc.html

【讨论】:

  • 不幸的是,instr 只能找到分隔符的第一个实例。假设您有字符串“asdfa:bfab:zarva”...您将如何找到第三个冒号分隔的单词?
  • @Michael 使用第一个匹配的位置+1作为下一个子串的起始位置,重复
【解决方案3】:

我喜欢@user1461607 的回答,除了:在我看来,SQLite 文档警告不要从 SELECT 中假设任何特定顺序,无论是在一般情况下,还是在递归 SELECT 的特定情况下。在这里,我修改了答案,以我认为 SQLite 保证工作的方式添加了一个排序列。

我还将示例从逗号分隔列表更改为路径,以表明在某些情况下您确实需要按特定顺序处理事物。此示例还打印出临时表中的所有列,因此更容易查看发生了什么。 AFAICT,SQLite 中的 CTE 没有通常的 ROWID 列,所以看起来确实需要自己添加一些排序列才能在晚上睡得香。

WITH RECURSIVE split(seq, word, str) AS (
    SELECT 0, '/', 'home/ronburk/layers/branch'||'/'
    UNION ALL SELECT
        seq+1,
        substr(str, 0, instr(str, '/')),
        substr(str, instr(str, '/')+1)
    FROM split WHERE str != ''
) SELECT * FROM split ORDER BY split.seq ASC;

【讨论】:

  • "split" 关键字可能不适用于棒棒糖之前的 android OS sqlite 版本。当我检查在 android OS 4.3 上运行的三星 Galaxy s3 设备时,它抛出错误并且无法执行包含“split”关键字的查询。错误:Caused by: android.database.sqlite.SQLiteException: near "split"
【解决方案4】:

@user1461607 提供的答案变体 确保保留任何碰巧为空字符串的 CSV 值:

WITH RECURSIVE split(value, str) AS (
      SELECT null, 'Auto,A,1234444' || ','  -- the string to be split 
      UNION ALL
      SELECT
      substr(str, 0, instr(str, ',')),
      substr(str, instr(str, ',')+1)
      FROM split WHERE str!=''
  ) SELECT value FROM split WHERE value is not NULL;

将 CSV 行转换为 JSON 数组

假设 JSON1 扩展已加载,您可以在最后一行使用 json_group_array(value) 进行转换 将 CSV 转换为 JSON 字符串数组。

【讨论】:

  • "split" 关键字可能不适用于棒棒糖之前的 android OS sqlite 版本。当我检查在 android OS 4.3 上运行的三星 Galaxy s3 设备时,它抛出错误并且无法执行包含“split”关键字的查询。错误:Caused by: android.database.sqlite.SQLiteException: near "split"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-25
  • 2015-04-01
  • 2010-11-06
  • 1970-01-01
相关资源
最近更新 更多