【问题标题】:From TCL use a variable in sqlite IN statement从 TCL 在 sqlite IN 语句中使用变量
【发布时间】:2018-09-12 09:13:06
【问题描述】:

我想对一个 sqlite 数据库执行以下查询:

set LCs [ DB eval { SELECT DISTINCT LC FROM   MyTable  WHERE LC IN ( 1, 3, 4 ) }  ]

这会产生所需的结果 1 3 4

尝试以下操作会引发语法错误:

设置 InString "1, 3, 4"

set LCs [ DB eval { SELECT DISTINCT LC FROM   MyTable  WHERE LC IN ( :InString ) } ]

我之前使用过 :Varaible 没有问题,但在这种情况下,由于大括号,它可能会失败。如何在 SQLite IN 语句中使用 TCL 变量?

【问题讨论】:

    标签: sqlite tcl


    【解决方案1】:

    如果您需要将一些值从 Tcl 移动到 SQLite 中以执行此类操作,请先将它们放入 :memory: 数据库中的临时表中,然后使用 SQL 操作从那里提取它们。

    DB eval {
        ATTACH DATABASE ':memory:' AS memdb;
        CREATE TEMP TABLE memdb.values (val TEXT);
    }
    foreach val {1 3 4} {
        DB eval {
            INSERT INTO memdb.values (val) VALUES (:val)
        }
    }
    set LCs [DB eval {
        SELECT DISTINCT LC FROM MyTable WHERE LC IN memdb.values.val
    }]
    

    【讨论】:

    • 有趣,直到看到你的回答我才知道:memory:。从现在开始,我肯定会考虑使用更多的东西,而不是在与我正在处理的数据库相同的数据库中使用临时表。
    • 使用 sqlite 3.21.0 我得到:接近“值”:执行创建临时表语句时出现语法错误,尽管我在语句中没有看到正式错误..
    • 按照此处给出的提示:stackoverflow.com/questions/52459126/… 建议的方法有效。
    【解决方案2】:

    根据文档:“Tcl 变量名可以出现在 SQL 语句 [...] 中任何可以放置字符串或数字文字的位置。”所以,你可以这样做:

    set LCs [DB eval {SELECT DISTINCT LC FROM MyTable WHERE LC IN (:v1, :v2, :v3)}]
    

    但您不能将变量用于完整列表。相反,您要么必须在将字符串传递给DB eval 之前构建字符串,要么创建一个函数来检查值是否在列表中。

    选项#1:

    set LCs [DB eval "SELECT DISTINCT LC FROM MyTable WHERE LC IN ($InString)"]
    

    选项 #2:

    proc check {val} {
        global InString
        return [expr {$val in $InString}]
    }
    db function search check
    set LCs [DB eval {SELECT LC FROM MyTable WHERE search(LC)}]
    

    对于选项#2,$InString 应该是一个普通的 Tcl 列表,所以不能用逗号分隔。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多