在1000s中选择整数时,SQlite查询不起作用

时间:2013-11-27 15:56:49

标签: c# sqlite

我正在使用c#,winforms,SQlite作为我的数据库。

我正在运行以下查询:

string sql14 = "select YYMM, TotalTrans  from t2 where CAST(TotalTrans as int) < 500000 and CAST(TotalTrans as int) > 1000";

然后我使用此查询来填充2个列表,然后我将其导出到menustrip,用户可以在其中选择它:

string sql14 = "select YYMM, TotalTrans  from t2 where CAST(TotalTrans as int) <  500000 and CAST(TotalTrans as int) > 1000";
SQLiteCommand cmd5 = new SQLiteCommand(sql14, sqlite_conn);


SQLiteDataReader rdr5 = cmd5.ExecuteReader();

while (rdr5.Read())
{

  int TotalTranst22;
  DateTime yyyymmt22;

  if (DateTime.TryParse(rdr5["YYMM"].ToString(), out yyyymmt22) && int.TryParse(rdr5["TotalTrans"].ToString(), out TotalTranst22))
  {
      // Populating the lists

      YYMMt22.Add(yyyymmt22);
      TotalTransIrregularitiest22.Add(TotalTranst22);
  }
}

问题:当我选择显示2个列表YMMt22和TotalTransIrrefularitiest22的内容的选项时,没有任何反应。在尝试调试时,我发现列表完全是空的,即:查询无效。

更新

当我尝试运行查询值&gt;时出现问题1000,因为他们有','  在他们中。

此外,在尝试用户建议时(下方)

SELECT CAST(TotalTrans as int) FROM t2`

我得到一个错误,说我的if语句

条件下索引超出了数组的范围

这是我试图通过查询存储在列表中的实际数据。如您所见,它确实有数千个分隔符(逗号)。

enter image description here


仅供记录:我知道查询我的表的过程是有效的,因为我使用了类似的查询来获取值<1000(注意它们没有',')并且它完美地工作。这是代码:

// Total Trans tolerance <1000

string sql13 = "select YYMM, TotalTrans  from t2 where cast(TotalTrans as int) < 1000";

更新

试过一个用户解决方案......仍然没有运气。列表没有填充任何数据

    string sql14 = "select YYMM, TotalTrans  from t2 where CAST(REPLACE(TotalTrans, ',', '') as int) < 500000 and CAST(REPLACE(TotalTrans, ',', '') as int) > 1000";
        SQLiteCommand cmd5 = new SQLiteCommand(sql14, sqlite_conn);


        SQLiteDataReader rdr5 = cmd5.ExecuteReader();

        while (rdr5.Read())
        {

            int TotalTranst22;


            DateTime yyyymmt22;
            if (DateTime.TryParse(rdr5["YYMM"].ToString(), out yyyymmt22) && int.TryParse(rdr5["TotalTrans"].ToString(), out TotalTranst22))
            {
                YYMMt22.Add(yyyymmt22);
                TotalTransIrregularitiest22.Add(TotalTranst22);
            }
        }

5 个答案:

答案 0 :(得分:3)

尝试类似下面的内容,我现在没有sqlite可用,所以可能需要稍微调整...

编辑:后来我注意到虽然你在WHERE子句中转换为int,但是你正在选择将使用逗号的TotalTrans的文本版本。这导致您的int.TryParse失败。尝试以下操作,它使用TryParse版本,它接受一个FormatProvider并可以处理逗号......

string sql14 = "select YYMM, TotalTrans  from t2 where CAST(REPLACE(TotalTrans, ',', '') as int) < 500000 and CAST(REPLACE(TotalTrans, ',', '') as int) > 1000"

SQLiteCommand cmd5 = new SQLiteCommand(sql14, sqlite_conn);
    SQLiteDataReader rdr5 = cmd5.ExecuteReader();

    while (rdr5.Read())
    {
        int TotalTranst22;
        DateTime yyyymmt22;
        if (DateTime.TryParse(rdr5["YYMM"].ToString(), out yyyymmt22) && int.TryParse(rdr5["TotalTrans"].ToString(), NumberStyles.Number, CultureInfo.CurrentCulture, out TotalTranst22))
        {
            YYMMt22.Add(yyyymmt22);
            TotalTransIrregularitiest22.Add(TotalTranst22);
        }
    }

请注意,这会为您提供一个短期解决方案,但您需要先询问为什么您的架构被定义为首先在字符串数据类型中保存数字。

答案 1 :(得分:2)

根据评论和屏幕截图,您的列确实是一个字符串,并且“数字”已经用逗号格式化。

如果允许您修改架构,也许您应该考虑这样做。如果您只在那里存储数字数据,为什么要使用字符串列?

如果您不被允许,您可以尝试在列上替换文本,删除导致问题的逗号。查看replace function并使用它来替换空字符串以删除逗号。

答案 2 :(得分:1)

我没有sqlite,我使用sql server试试这段代码,也许可以帮到你:

<强> 1。如果TotalTrans是一个字符串

  • 您必须将','替换为空字符串

<强> 2。如果TotalTrans是十进制('。') - 2.15

  • 你必须转换为float

select 
    convert(float, replace(TotalTrans,',',''))
from
(
    select '336,604' as TotalTrans 
    union all
    select '329,548' as TotalTrans 
    union all
    select '2,734,311' as TotalTrans 
    union all
    select '2.15' as TotalTrans -- [done] with convert to float
    union all
    select '4' as TotalTrans 
    union all
    select '78' as TotalTrans 
    union all
    select '' as TotalTrans -- [done] automatic replace to 0
    union all
    select null as TotalTrans -- [done] no record
) a
where cast(replace(TotalTrans,',','') as float) < 1000 

结果:

--------
|2.15  |
--------
|4     |
--------
|78    |
--------
|0     |
--------

答案 3 :(得分:1)

我们知道大于999的整数将有4位或更多位数。

SELECT YYMM, TotalTrans FROM t2 WHERE length(TotalTrans) > 3;

您也可以尝试BETWEEN语法而不是两个子句约束。

 SELECT YYMM, TotalTrans FROM t2 WHERE CAST(replace(TotalTrans,',','') BETWEEN 1000 AND 500000;

这将强制转换发生一次,这可能会阻止使用任何临时表。

正如其他人所说,你的问题在于整数的文本表示。您可能已经意识到这一点,但您认为这是一种权衡;但是,数据库用于存储数据,而您的应用程序用于存储数据。让C#为你做数字格式化。

How to display numeric in 3 digit grouping

并修好你的桌子。

UPDATE t2 SET TotalTrans = CAST(replace(TotalTrans,',','') AS INTEGER);

请记住,SQLite在每个字段的基础上使用类型关联,因此您不需要更新架构 - 我建议您这样做。

所有这一切,如果你想知道为什么这种情况发生,我怀疑它正在为每个约束创建一个临时表,因为所有类型的杂耍,迫使SQLite执行一个有趣的3表加入。最好的办法是在查询上运行EXPLAIN命令,看看SQLite是如何解决这个问题的。

答案 4 :(得分:1)

你的问题在这里

if (DateTime.TryParse(rdr5["YYMM"].ToString(), out yyyymmt22) && int.TryParse(rdr5["TotalTrans"].ToString(), out TotalTranst22))

int.TryParse失败了。 请记住,您正在选择字符串值,然后尝试将其转换为int。要使查询正常工作,您需要将其更改为

select YYMM, REPLACE(TotalTrans, ',', '')  from t2 where CAST(REPLACE(TotalTrans, ',', '') as int) < 500000 and CAST(REPLACE(TotalTrans, ',', '') as int) > 1000";

否则在if条件下TransValue将类似于'336,604'并且int.TryParse()将失败。

希望这会有所帮助。