我可能又做了一些愚蠢的事情,但我不明白下面查询中的参数替换。列
char_len
被声明为整数。
在 SQLite 查询中,Tcl 变量
selEnd
被替换为字符串,因为查询返回所有行,就好像条件始终为 true 一样。我应该写下 selENd
出现在查询中 UNION ALL
行 WHERE
中的 and p.char_len + p.char_bgn <= :selEnd
之后。
如果
selEnd
的声明更改为set selEnd [expr {799+1}]
,则仅返回应返回的行。
如果使用
.param set :selEnd 800
在 CLI 或 SQLite Fiddle 中运行相同的查询,则 selEnd
被视为整数。如果我只是输入 800
而不是 :selEnd
,则会返回正确的行。
如果使用双引号而不是大括号设置变量
SQL
,并且将条件更改为使用 $selEnd
而不是 :selEnd
,则会返回正确的行。
我不明白什么会导致在使用大括号设置
:selEnd
时将 '800'
视为 800
而不是 SQL
?
我认为 Tcl 将所有内容都视为字符串,直到它被“用于”某些东西为止。
SQL
只是一个字符串,其中 selEnd
将作为 800
插入;但是,似乎使用 :selEnd
类型参数替换决定了 selEnd
是一个字符串,应该作为 '800'
插入。为什么?
谢谢你。
set docId 1
set selStart 500
set selEnd 800; #[expr {799+1}]
set SQL {\
with recursive
pieces( order_idx, doc_id, key, buffer_id, char_start, char_len, char_bgn ) as
(
select
0,
r.*,
0
from
pt_pointers r
where
r.key = (select order_keys->>0 from ur_maps where doc_id = :docId)
and r.doc_id = :docId
UNION ALL
select
order_idx + 1,
r.*,
p.char_len + p.char_bgn
from pt_pointers as r, pieces p
where r.key = (select order_keys->>(order_idx+1) from ur_maps where doc_id = :docId)
and p.char_len + p.char_bgn <= :selEnd
and r.doc_id = :docId
)
select *
from pieces;\
}
db eval $SQL {
chan puts stdout "$order_idx, $doc_id, $key, $buffer_id, $char_start, $char_len, $char_bgn"
}
我在 SQLite 论坛上问了这个问题,Dr.希普的答案是:
在TCL,一切都是字符串,至少理论上是这样。在引擎盖下, TCL 跟踪整数和浮点值等。 但我们的想法是,在开发人员级别,一切都正常进行 是一个纯字符串。 (事实上,在 Tcl8.0 之前,一切都真的 始终是一个字符串。其他数据类型在 Tcl8.0 中引入为 优化。)
SQLite 背离了 TCL 中的一切都是字符串的想法。 绑定时,如果底层 TCL 值具有某种表示形式 除了字符串之外,SQLite 尝试使用替代表示形式。 从技术上讲,这违反了规则,为此我已经 斥责。但现在不能在不破坏的情况下改变设计 兼容性,所以就是这样。
通常,Tcl/SQLite 界面“正常工作”,无需您 开发商必须要考虑一下。但如果你进入一些 复杂的情况,就像你似乎遇到的那样,那么这样做总是没有坏处的 CAST 你的绑定