【问题标题】:PHP MySQL - How to insert default value in a prepared statementPHP MySQL - 如何在准备好的语句中插入默认值
【发布时间】:2016-06-01 17:13:35
【问题描述】:

假设我有一个准备好的语句,如下所示:

$insertSql = "";
$insertSql .= "INSERT INTO table";
$insertSql .= "(tag,month_interval,month_interval_lastupdated,date_due,date_due_lastupdated,date_completion,date_completion_lastupdated,";
$insertSql .= "activeNotification,date_lastmodified) ";
$insertSql .= "VALUES (?,?,NOW(),?,NOW(),?,NOW(),?,NOW())";

但有时其中一些问号不会设置。

我可以在准备好的语句中替换一个关键字来告诉 MySQL 插入默认值吗?

类似:

if($stmt = $mysqli->prepare($insertSql)) {
   if(!isset($tag)) {
      // code to find first question mark and replace w/ default value
      }
      $stmt->bind_param('sisss',$tag,$month_interval,$date_due,$date_completion);
      $stmt->execute();
}

日期字段的默认值为 '1000-01-01 00:00:00',month_interval 的默认值为 0,其余字段的默认值为 NULL。

【问题讨论】:

  • 我希望您不要将您的第一个代码块视为准备好的语句,因为准备好的语句位是您的第二个代码块。是否需要分 5 部分生成 sql?另外,默认值是多少?
  • 日期的默认值为'1000-01-01 00:00:00',month_interval的默认值为0,其余默认为NULL。

标签: php mysql insert prepared-statement


【解决方案1】:

我有同样的问题,所以我将这个答案 https://stackoverflow.com/a/13867665/1251063 改编为 php 准备好的声明:

if(!($stmt = $this->conn->prepare("INSERT INTO mytable (myfield) VALUES (IFNULL(?,DEFAULT(myfield)))"))){
    throw new Exception("Prepare failed: (" . $this->conn->errno . ") " . $this->conn->error);
}

if(!($stmt->bind_param("s",$myfield))) { //$myfield is a variable that can be null, if so the default value for such field will be inserted
    throw new Exception("Bind_param failed: (" . $this->conn->errno . ") " . $this->conn->error);
}

if(!$stmt->execute()) {
    throw new Exception("Execute failed: (" . $stmt->errno . ") " . $stmt->error);
}

【讨论】:

  • 这看起来像我要找的。让我试一试,如果它有效,我会接受。本质上,DEFAULT(field) 函数就是我想要的。我认为IFNULL部分可以在php端完成。
  • 其实我可以做到INSERT INTO table SET date=DEFAULT;
【解决方案2】:

只是一个想法,如果你有一个条件,当你不知道所有的值时,你应该准备语句,甚至不添加这些值。

同样在一些情况下(例如在autoincrement字段)你可以插入一个NULL来触发插入默认值,但是如果字段定义允许NULL's插入NULL会插入NULL,请务必小心。

【讨论】:

  • 如果值类似于2015-01-01 23:32:23 并且用户输入nothing 以指示该值是null 或default,该怎么办。你仍然希望它在准备好的语句中
  • 对我来说这更重要,因为我有脚本在数据库中的日期上运行计算。如果该值弹出为NULL,那就是个大问题了。
  • 出于可移植性的原因,我强烈建议不要这样做,它不适用于所有版本,我的服务器版本是 5.6.37,它不起作用
【解决方案3】:

在我看来,您的问题涉及一个有趣的主题。

通过快速搜索,我没有找到任何预定义的解决方案,但我会在接下来的几天里继续搜索。

我已经制定了一个解决方案,但它有点扭曲,并不完全干净。

首先,我用占位符重新定义查询:

$query = "
    INSERT INTO table
                (
                    tag,
                    month_interval,
                    month_interval_lastupdated,
                    date_due,
                    date_due_lastupdated,
                    date_completion,
                    date_completion_lastupdated,
                    activeNotification,
                    date_lastmodified
                )
         VALUES (<tag>,<month_interval>,NOW(),<date_due>,NOW(),<date_completion>,NOW(),<activeNotification>,NOW())
";

在此示例中,我使用&lt;&gt; 包围占位符,但您可以选择您喜欢的占位符,确保它们不会与查询的其他元素混淆。

然后,我初始化一个关联数组,其中键作为占位符名称和要绑定的值,以及一个具有完整绑定类型集的变量 ($types):

$values = array( 'tag'=>$tag, 'month_interval'=>$month_interval, 'date_due'=>$date_due, 'date_completion'=>$date_completion, 'activeNotification'=>$activeNotification );
$types = 'sisss';

然后,最重要的一行。我以这种奇怪的方式初始化一个数组:

$bind = array( Null, '' );

索引0设置为Null,因为是为stmt对象保留的(在下面创建);索引 1 是一个空字符串,将填充必要的绑定类型。

现在我对数组$values 的所有元素执行foreach 循环:

$i = 0;
foreach( $values as $key => $val )
{
    if( is_null( $val ) )
    {
        $query = str_replace( '<'.$key.'>', 'DEFAULT', $query );
    }
    else
    {
        $query    = str_replace( '<'.$key.'>', '?', $query );
        $bind[1] .= $types[$i];
        $bind[]   = &$val;
    }
    $i++;
}

在该循环中,如果值为 null,我将相应查询的占位符替换为 mySQL 关键字 DEFAULT。否则,我将占位符替换为?,将相应的$types 子字符串添加到$bind[1],并将值(通过引用)附加到$bind 数组。

至此,真正的查询准备好了,我可以准备好了:

$stmt = $db->prepare( $query ) or die( $stmt->error );

而且,如果没有默认值 (count($bind)&gt;2),我可以绑定它:

if( count($bind)>2 )
{
    $bind[0] = $stmt;
    call_user_func_array( 'mysqli_stmt_bind_param', $bind );
}

如前所述,我将$bind[0]设置为-&gt;prepare返回的stmt对象,然后我使用call_user_func_array执行mysqli_stmt_bind_param。我不能直接调用-&gt;bind_param,因为我有一个可变参数号。

在这个古怪的过程结束后,我终于可以执行查询了:

$stmt->execute() or die( $stmt->error );

我已经测试了这段代码,它可以工作。

主要问题在于is_null( $val ):使用数组,我不能使用isset 作为测试,因为数组的每个元素都是偶数设置的。如果所有允许 Null 值的占位符字段都具有 Null 广告默认值,则该代码有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-24
    • 1970-01-01
    相关资源
    最近更新 更多