【问题标题】:PDO losing decimal precision when updating record更新记录时 PDO 丢失小数精度
【发布时间】:2017-10-10 07:41:12
【问题描述】:

我正在尝试使用 HTML 表单和 PHP 脚本来更新我的数据库中的表,我正在使用带有准备好的语句和命名占位符的 pdo

这是执行前的sql:

UPDATE lctn_bt SET `BTlongitude` = :BTlongitude, `BTlatitude` = :BTlatitude, `BTaccuracy` = :BTaccuracy, `BTnotes` = :BTnotes, `ISShaft` = :ISShaft, `ClientID` = :ClientID WHERE BTid = 79

这是我输入执行语句的数组:

Array ( [:BTlongitude] => 144.9687500 [:BTlatitude] => -37.7452700 [:BTaccuracy] => 4 [:BTnotes] => Audit. To right of driveway [:ISShaft] => [:ClientID] => 0 )

这是构建语句并执行它的代码:

$sql4 = "UPDATE ".$table." SET ";

    foreach($values3 as $key => $string){
        if($fields[$key] !== $primaryID){
            $sql4 = $sql4."`".$fields[$key]."` = :".$fields[$key].", ";
            $prepared[':'.$fields[$key]] = $string;
            echo $fields[$key].': '.$string.'</br>';
        }
    }
    $sql4 = substr($sql4, 0, -2);
    $sql4 = $sql4." WHERE ".$primaryID." = ".$record;
    echo $sql4;
    $sql4 = $dbh->prepare($sql4);
    $out = $sql4->execute($prepared);

如果我要在数组顶部执行该语句,即使数据库中的 2 个字段设置为“十进制(12 ,7)" 和同一张表中的其他记录正在存储完整值。事实上,我试图存储的值最初是从该表中读取的。

但是,如果我使用 SQL 语句并手动输入值,然后使用 phpMyAdmin 运行 SQL,它可以正常工作并存储小数位。

这让我很头疼,我能在网上找到的唯一其他具有相同问题的帖子源于人们试图将小数位存储在没有定义小数位的小数字段中(例如小数(10,0))

上面的数组是一个 print_r($prepared);放在最后一行之后 ($out = $sql4->execute($prepared);) 并显示正确的值。

如果我运行以下代码,则记录添加成功,所有小数位不变:

$prepared = array(':BTlongitude' => 144.9687500, ':BTlatitude' => -37.7452700, ':BTaccuracy' => 4, ':BTnotes' => "Audit. To right of driveway", ':ISShaft' => '',':ClientID' => 0, ':BTid' => 79);

$dbh = new PDO("mysql:host=$db->host;dbname=$db->db_name", $db->username, $db->password);

$sql = "UPDATE lctn_bt SET `BTlongitude` = :BTlongitude, `BTlatitude` = :BTlatitude, `BTaccuracy` = :BTaccuracy, `BTnotes` = :BTnotes, `ISShaft` = :ISShaft, `ClientID` = :ClientID WHERE BTid = :BTid";
$sql = $dbh->prepare($sql);
$out = $sql->execute($prepared);

表格是这样设置的:

CREATE TABLE `lctn_bt` (
 `BTid` int(11) NOT NULL,
 `BTproperty` int(11) DEFAULT NULL,
 `BTlongitude` decimal(12,7) DEFAULT NULL,
 `BTlatitude` decimal(12,7) DEFAULT NULL,
 `BTaccuracy` int(11) DEFAULT NULL,
 `BTnotes` varchar(1000) DEFAULT NULL,
 `ISShaft` int(11) DEFAULT NULL,
 `ClientID` int(11) DEFAULT '0',
 `LastUpdated` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

【问题讨论】:

  • 您需要确定对值进行四舍五入的位置。在循环之前添加var_dump($values3),在之后添加var_dump($prepared)。这些值是四舍五入还是看起来正确?如果您已经这样做了,请在您的问题中清楚说明
  • 我在上面发布的那个数组是一个 print_r($prepared) 我在执行 SQL 后的代码中,以检查那个确切的东西。它似乎在 $sql4->execute($prepared);或在 MySQL 端。你还有其他提示吗?感谢您花时间查看我的代码 :)
  • 这行得通:$prepared = array(':BTlongitude' =&gt; 144.9687500, ':BTlatitude' =&gt; -37.7452700, ':BTaccuracy' =&gt; 4, ':BTnotes' =&gt; "Audit. To right of driveway", ':ISShaft' =&gt; '',':ClientID' =&gt; 0, ':BTid' =&gt; 79); $dbh = new PDO("mysql:host=$db-&gt;host;dbname=$db-&gt;db_name", $db-&gt;username, $db-&gt;password); $sql = "UPDATE lctn_bt SET 'BTlongitude' = :BTlongitude, 'BTlatitude' = :BTlatitude, 'BTaccuracy' = :BTaccuracy, 'BTnotes' = :BTnotes, 'ISShaft' = :ISShaft, 'ClientID' = :ClientID WHERE BTid = :BTid"; $sql = $dbh-&gt;prepare($sql); $out = $sql-&gt;execute($prepared); 我看不出我的代码哪里错了
  • 如果你不能重现它,那么你的问题不适合 Stack Overflow,很抱歉。

标签: php mysql pdo


【解决方案1】:

原来是选角的问题。我正在使用:

$somevalue = htmlentities($_POST'somevalue'], ENT_HTML5, 'UTF-8');

在代码的更远处,我认为它将小数位转换为等效的 html 实体。

我换成了

$somevalue = htmlspecialchars($_POST'somevalue'], ENT_HTML5, 'UTF-8');

然后在我为 pdo 构建值数组的地方检查数字并使用以下代码强制类型转换为浮点数:

if(is_numeric($string)){
    $prepared[':'.$fields[$key]] = floatval($string);
} else {
    $prepared[':'.$fields[$key]] = $string;
}

这似乎成功了。

【讨论】:

  • 您应该从不对存储值进行编码。编码是为了显示。见stackoverflow.com/questions/38411112/…
  • 另外,尽量不要通过 HTML 文档进行调试。最好使用实际的调试器,或者,如果您必须转储变量,则以纯文本形式进行。
猜你喜欢
  • 1970-01-01
  • 2013-07-25
  • 2013-06-27
  • 1970-01-01
  • 2012-05-13
  • 1970-01-01
  • 2021-09-26
  • 1970-01-01
  • 2013-05-02
相关资源
最近更新 更多