【问题标题】:Cannot INSERT date with prepared statement无法使用准备好的语句插入日期
【发布时间】:2018-09-27 10:43:47
【问题描述】:

我正在尝试为给定月份/年份的每一天执行多行 INSERT。

如果循环只运行一次,一切都会按预期进行。如果它运行 2 次或更多次,则会引发以下错误:

SQLSTATE[22018]:强制转换规范的字符值无效:206 [Microsoft][ODBC SQL Server Driver][SQL Server]操作数类型冲突:文本与日期不兼容(SQLExecute[206] at ext\pdo_odbc\odbc_stmt. c:260)

如果我不准备日期,它也可以。我不知所措......我做错了什么吗?这是我的代码:

$query = "INSERT INTO scp.schedule
    (record_create_date, associate_id, scheduled_date, shift_id, is_weekend)
    VALUES ";

for ($day_count = 1; $day_count <= $days_month; $day_count++)
{
    $day_count = sprintf("%02d", $day_count);

    $full_date = $year . "-" . $month . "-" . $day_count;

    // Check if date is weekend
    $weekend = (date("N", strtotime($full_date)) < 6) ? 0 : 1;

    $query .= "(GETDATE(), ?, ?, ?, ?), ";
    $params[] = $associate["associate_id"];
    $params[] = $full_date;
    $params[] = $shifts[0]["shift_id"];
    $params[] = $weekend;
}

// Remove the last comma and space
$query = substr($query, 0, -2);

$stmt = $db->prepare($query);
$stmt->execute($params);

我使用的是 SQL 服务器版本 12+ 和 PHP 版本 7+。 DB 中的列类型是 DATE。

编辑:

这行得通

INSERT INTO scp.schedule 
    (record_create_date, associate_id, 
     scheduled_date, shift_id, is_weekend) 
VALUES (GETDATE(), ?, ?, ?, ?)

这不是

INSERT INTO scp.schedule 
    (record_create_date, associate_id, 
     scheduled_date, shift_id, is_weekend) 
VALUES (GETDATE(), ?, ?, ?, ?), 
       (GETDATE(), ?, ?, ?, ?)

编辑 2:

一些测试和它们抛出的错误。我也尝试过使用'?'

$query .= "(GETDATE(), ?, DATEFROMPARTS(?, ?, ?), ?, ?), ";
// Also tried intval() and casting to int
$params[] = $year;
$params[] = $month;
$params[] = $day_count;

SQLSTATE[22018]:强制转换规范的字符值无效:206 [Microsoft][ODBC SQL Server Driver][SQL Server]操作数类型冲突:文本与 int 不兼容(SQLExecute[206] at ext\pdo_odbc\odbc_stmt. c:260)

$query .= "(GETDATE(), ?, CONVERT(date, ?), ?, ?), ";

SQLSTATE[22018]:转换规范的字符值无效:529 [Microsoft][ODBC SQL Server Driver][SQL Server]不允许从数据类型文本到日期的显式转换。 (SQLExecute[529] at ext\pdo_odbc\odbc_stmt.c:260)

【问题讨论】:

  • 对于我们这些懒得弄清楚查询是什么样子的人,您能否将echo $query; 的结果添加到您的问题中,以便我们可以看到您实际尝试运行的内容作为查询
  • $full_date 看起来像什么?请记住 DATE 列不是 DATETIME 列。
  • @RiggsFolly 编辑了帖子
  • @delboy1978uk $full_date 看起来像“2018-10-01”
  • 您在$params 中没有足够的值来满足查询中的所有?

标签: php sql-server date pdo prepared-statement


【解决方案1】:

您可以尝试避免使用DATEFROMPARTS()CONVERT() T-SQL 函数将字符串作为 SQL Server 中日期字段的值传递。

<?
$query = "INSERT INTO scp.schedule
    (record_create_date, associate_id, scheduled_date, shift_id, is_weekend)
    VALUES ";

for ($day_count = 1; $day_count <= $days_month; $day_count++) {
    $day       = $day_count;
    $day_count = sprintf("%02d", $day_count);
    $full_date = $year . "-" . $month . "-" . $day_count;

    // Check if date is weekend
    $weekend = (date("N", strtotime($full_date)) < 6) ? 0 : 1;

    # Using DATETIMEFROMPARTS
    $query .= "(GETDATE(), ?, DATEFROMPARTS(?, ?, ?), ?, ?), ";
    $params[] = $associate["associate_id"];
    $params[] = $year;
    $params[] = $month;
    $params[] = $day;
    $params[] = $shifts[0]["shift_id"];
    $params[] = $weekend;

    # Using CONVERT
    /*
    $query .= "(GETDATE(), ?, CONVERT(date, ?), ?, ?), ";
    $params[] = $associate["associate_id"];
    $params[] = $full_date;
    $params[] = $shifts[0]["shift_id"];
    $params[] = $weekend;
    */
}

// Remove the last comma and space
$query = substr($query, 0, -2);
$stmt = $db->prepare($query);
$stmt->execute($params);

?>

如果不需要在一个语句中插入所有日期,您可以考虑准备一次语句并在每次迭代中执行它。 然后,如果发生错误,您将知道是什么值导致了问题。

【讨论】:

  • 我试过DATEFROMPARTS(),因为我的专栏是DATE,现在我得到了一个不同的错误:文本与int不兼容。我什至尝试在$year, $month, $day 上使用intval(),同样的事情。我之前试过CONVERT/CAST选项,但我不记得错误了,我再试一次
  • @IcedAnt 你能在此处回显并发布 $year, $month, $day - 可能有一些意想不到的值吗?谢谢。
  • 我可以,但不太可能,因为$query .= "(GETDATE(), ?, '" . $full_date . "', ?,?), "; 工作正常
  • echo $year . $month . $day_count . " "; 20181001 20181002 20181003 20181004 20181005 20181006 20181007 20181008 20181009 20181010 20181011 20181012 20181013 20181014 20181015 20181016 20181017 20181018 20181019 20181020 20181021 20181022 20181023 20181024 20181025 20181026 20181027 20181028 20181029 20181030 20181031
  • 我已经尝试过了,它适用于一次迭代,但不适用于 2 次或更多次。这个字段绝对是问题,因为当我不准备 $full_date 时查询工作正常
【解决方案2】:

尝试使用trim 而不是substr

$query = trim(trim($query), ',');

内部trim 将删除space,外部trim 将删除,

【讨论】:

  • 这与我的问题有什么关系? substr 工作正常,使用trim 有什么意义?
  • 正如您所说的它对单个记录工作正常,这意味着查询没有任何问题。因此,唯一可能导致问题的是 substr。您是对的,substr 似乎没有任何问题,但请尝试一下。
  • 如果循环运行不止一次,我看不出substr 会如何产生不同的结果......无论如何,它只会删除最后两个字符,这些字符始终是逗号和空间。你能解释一下吗?
  • 是的,应该不会有任何不同的结果,但修剪时间复杂度低于 substr。
猜你喜欢
  • 2016-04-10
  • 1970-01-01
  • 2014-03-29
  • 1970-01-01
  • 1970-01-01
  • 2015-03-02
  • 2016-03-07
  • 1970-01-01
  • 2012-07-08
相关资源
最近更新 更多