MySQL(或c#)不匹配双精度或小数
本文关键字:双精度 小数 不匹配 MySQL | 更新日期: 2023-09-27 18:10:48
为什么MySQL,或者c#我不知道哪一个,不喜欢匹配双精度或十进制变量?它将匹配字符串,但我需要一个双精度或小数,因为我需要匹配大于或小于小数的位置。它不匹配任何小数或双精度,也不给出任何错误。这是我的代码:
double lat5 = -26.00033;
string Lati = "-26.00033";
decimal lat6 = decimal.Parse(Lati, CultureInfo.InvariantCulture);
//this
CommandString = "SELECT * FROM lapdetails2 WHERE Latitude = -26.00033";
//and this work
CommandString = "SELECT * FROM lapdetails2 WHERE Latitude = '" + Lati + "'";
//but this
CommandString = "SELECT * FROM lapdetails2 WHERE Latitude = '" + lat5 + "'";
//and this do not work
CommandString = "SELECT * FROM lapdetails2 WHERE Latitude = '" + lat6 + "'";
MySQL数据库中的数据是DOUBLE(10,5).
编辑:这是一个参数化查询我尝试:
CommandString = "SELECT * FROM lapdetails2 WHERE Latitude = @Latitude";
MySqlCommand cmd = new MySqlCommand(CommandString);
cmd.Connection = DB.ConnectSQL;
cmd.Parameters.AddWithValue("@Latitude", lat6);
cmd.Connection.Open();
MySqlDataReader reader = cmd.ExecuteReader();
我还按照Rick James的建议将DB数据更改为DECIMAL(8,5),但它仍然不起作用。
编辑2:我修复了这个与存储过程(不是很有效,但它的工作)。
CREATE DEFINER=```localhost` PROCEDURE `coord_pro`(IN Longi1 double(8,5), IN Longi2 double(8,5), IN lat double(8,5))
BEGIN
create table tmp engine=memory select *
from lapdetails2 where Latitude = lat AND Longitude >= Longi2 AND Longitude <= Longi1;
END
,Longi1 = actualLong * 1.00001;
和Longi2 = actualLong * 0.99991;
,然后从tmp
读取值,根据您的精度,应该只有一行。
当转换为字符串:
时,您必须使用InvariantCulture
// this should be OK
CommandString = "SELECT * FROM lapdetails2 WHERE Latitude = '" + lat5.ToString(CultureInfo.InvariantCulture) + "'";
使用CultureInfo.InvariantCulture
确保.
将用作小数分隔符。更好的方法是消除撇号'
,并让DMBS比较数字,而不是字符串:
CommandString = "SELECT * FROM lapdetails2 WHERE Latitude = " + lat5.ToString(CultureInfo.InvariantCulture);
首先,不要在FLOAT
或DOUBLE
上使用(M,N)
,这会导致额外的四舍五入。
使用DECIMAL(8,5)
,如果你总是有5位小数在你的后期/液化天然气的数字。Decimal将精确地与-26.00033进行比较,无论是否加引号。
一般来说,比较本质上是"浮点数"的相等数是不明智的,例如纬度/经度。
当在c#中工作时,请确保将其四舍五入到小数点后5位,并为一致性提供给MySQL一个字符串,而不是FLOAT
或DOUBLE
。(也许%.5f
格式在c#中可以像C一样工作?)
附录
给定表d DECIMAL(18,4)
:
mysql> SELECT d, d<1.2346, d<'1.2346',
d=1.2346, d='1.2346',
d>1.2346, d>'1.2346' FROM `dec184` WHERE d = 1.2346;
+--------+----------+------------+----------+------------+----------+------------+
| d | d<1.2346 | d<'1.2346' | d=1.2346 | d='1.2346' | d>1.2346 | d>'1.2346' |
+--------+----------+------------+----------+------------+----------+------------+
| 1.2346 | 0 | 0 | 1 | 1 | 0 | 0 |
+--------+----------+------------+----------+------------+----------+------------+
当客户端(c#,在你的情况下)构建值时,它必须转换为字符串并可选地引用它。注意1.2346
在所有情况下是如何正确工作的。
现在,让我们改变一下。dx
被声明为FLOAT
:
mysql> SELECT d, dx, dx<1.2346, dx<'1.2346',
dx=1.2346, dx='1.2346',
dx>1.2346, dx>'1.2346' FROM `dec184` WHERE d = 1.2346;
+--------+--------+-----------+-------------+-----------+-------------+-----------+-------------+
| d | dx | dx<1.2346 | dx<'1.2346' | dx=1.2346 | dx='1.2346' | dx>1.2346 | dx>'1.2346' |
+--------+--------+-----------+-------------+-----------+-------------+-----------+-------------+
| 1.2346 | 1.2346 | 1 | 1 | 0 | 0 | 0 | 0 |
+--------+--------+-----------+-------------+-----------+-------------+-----------+-------------+
注意dx
是如何在常量下面的。为了验证,让我们欺骗MySQL提供一个更精确的值。(注:FLOAT
只能容纳7位有效数字,存储在24位)
mysql> SELECT dx, dx+0 FROM `dec184` WHERE d = 1.2346;
+--------+--------------------+
| dx | dx+0 |
+--------+--------------------+
| 1.2346 | 1.2345999479293823 |
+--------+--------------------+
还是……
mysql> SELECT ROUND(dx,5), ROUND(dx,9) FROM `dec184` WHERE d = 1.2346;
+-------------+-------------+
| ROUND(dx,5) | ROUND(dx,9) |
+-------------+-------------+
| 1.23460 | 1.234599948 |
+-------------+-------------+