使用 DEFAULT 值准备 MySQL INSERT/UPDATE 语句

发布于 2024-08-25 22:42:37 字数 962 浏览 6 评论 0 原文

引用 MySQL INSERT 手册 - UPDATE 也是如此:

使用关键字 DEFAULT 将列显式设置为其默认值。这使得编写将值分配给除几列之外的所有列的 INSERT 语句变得更加容易,因为它使您能够避免编写不包含表中每列的值的不完整 VALUES 列表。否则,您必须写出与 VALUES 列表中的每个值对应的列名称列表。

简而言之,如果我写

INSERT INTO table1 (column1,column2) values ('value1',DEFAULT);

一个将column2设置为其默认值的新行(无论它是什么),则会被插入。

但是,如果我在 PHP 中准备并执行一条语句:

$statement = $pdoObject->
    prepare("INSERT INTO table1 (column1,column2) values (?,?)");
$statement->execute(array('value1','DEFAULT'));

如果该列能够存储文本值,则新行将包含“DEFAULT”作为其文本值。

现在我已经为 PDO 编写了一个抽象层(我需要它),为了解决这个问题,我正在考虑引入一个

const DEFAULT_VALUE = "randomstring";

所以我可以执行这样的语句:

$statement->execute(array('value1',mysql::DEFAULT_VALUE));

然后在进行绑定的方法中,我将遍历发送的值被绑定,如果 some 等于 self::DEFAULT_VALUE,则采取相应的行动。

我很确定有更好的方法来做到这一点。其他人也遇到过类似的情况吗?

Quoting MySQL INSERT manual - same goes for UPDATE:

Use the keyword DEFAULT to set a column explicitly to its default value. This makes it easier to write INSERT statements that assign values to all but a few columns, because it enables you to avoid writing an incomplete VALUES list that does not include a value for each column in the table. Otherwise, you would have to write out the list of column names corresponding to each value in the VALUES list.

So in short if I write

INSERT INTO table1 (column1,column2) values ('value1',DEFAULT);

A new row with column2 set as its default value - whatever it may be - is inserted.

However if I prepare and execute a statement in PHP:

$statement = $pdoObject->
    prepare("INSERT INTO table1 (column1,column2) values (?,?)");
$statement->execute(array('value1','DEFAULT'));

The new row will contain 'DEFAULT' as its text value - if the column is able to store text values.

Now I have written an abstraction layer to PDO (I needed it) and to get around this issue am considering to introduce a

const DEFAULT_VALUE = "randomstring";

So I could execute statements like this:

$statement->execute(array('value1',mysql::DEFAULT_VALUE));

And then in method that does the binding I'd go through values that are sent to be bound and if some are equal to self::DEFAULT_VALUE, act accordingly.

I'm pretty sure there's a better way to do this. Has someone else encountered similar situations?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

甜柠檬 2024-09-01 22:42:37

我知道的唯一“解决方法”是使用 Coalesce ()默认(字段名称)

例如

$pdo = new PDO("mysql:host=localhost;dbname=test", 'localonly', 'localonly'); 
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$pdo->exec("
  CREATE TEMPORARY TABLE foo (
    id int auto_increment,
    x int NOT NULL DEFAULT 99,
    y DATETIME NOT NULL DEFAULT '2010-03-17 01:00:00',
    z varchar(64) NOT NULL DEFAULT 'abc',
    primary key(id)
  )
");


$stmt = $pdo->prepare('
  INSERT INTO
    foo
    (x,y,z)
  VALUES
    (
      Coalesce(:x, Default(x)),
      Coalesce(:y, Default(y)),
      Coalesce(:z, Default(z))
    )
');
$stmt->bindParam(':x', $x);
$stmt->bindParam(':y', $y);
$stmt->bindParam(':z', $z);


$testdata = array(
  array(null, null, null),
  array(1, null, 'lalala'),
  array(null, '2009-12-24 18:00:00', null)
);
foreach($testdata as $row) {
  list($x,$y,$z) = $row;
  $stmt->execute();
}
unset($stmt);
foreach( $pdo->query('SELECT id,x,y,z FROM foo', PDO::FETCH_NUM) as $row) {
  echo join(', ', $row), "\n";
}

打印

1, 99, 2010-03-17 01:00:00, abc
2, 1, 2010-03-17 01:00:00, lalala
3, 99, 2009-12-24 18:00:00, abc

The only "workaround" I know for this is to use Coalesce() and Default(fieldname)

E.g.

$pdo = new PDO("mysql:host=localhost;dbname=test", 'localonly', 'localonly'); 
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$pdo->exec("
  CREATE TEMPORARY TABLE foo (
    id int auto_increment,
    x int NOT NULL DEFAULT 99,
    y DATETIME NOT NULL DEFAULT '2010-03-17 01:00:00',
    z varchar(64) NOT NULL DEFAULT 'abc',
    primary key(id)
  )
");


$stmt = $pdo->prepare('
  INSERT INTO
    foo
    (x,y,z)
  VALUES
    (
      Coalesce(:x, Default(x)),
      Coalesce(:y, Default(y)),
      Coalesce(:z, Default(z))
    )
');
$stmt->bindParam(':x', $x);
$stmt->bindParam(':y', $y);
$stmt->bindParam(':z', $z);


$testdata = array(
  array(null, null, null),
  array(1, null, 'lalala'),
  array(null, '2009-12-24 18:00:00', null)
);
foreach($testdata as $row) {
  list($x,$y,$z) = $row;
  $stmt->execute();
}
unset($stmt);
foreach( $pdo->query('SELECT id,x,y,z FROM foo', PDO::FETCH_NUM) as $row) {
  echo join(', ', $row), "\n";
}

prints

1, 99, 2010-03-17 01:00:00, abc
2, 1, 2010-03-17 01:00:00, lalala
3, 99, 2009-12-24 18:00:00, abc
a√萤火虫的光℡ 2024-09-01 22:42:37

我尝试回复 VolkerK 的答案,但找不到如何回复。 :( 我对这一切都有点陌生。

无论如何,我创建了一个 mysql 函数来与他的 COALESCE 想法结合使用

CREATE FUNCTION NULLDEFAULT(colname VARCHAR(64), tablename VARCHAR(64), dbname VARCHAR(64)) RETURNS longtext DETERMINISTIC READS SQL DATA
BEGIN
    DECLARE retval longtext;
    SELECT
        COLUMN_DEFAULT INTO retval 
    FROM
        information_schema.COLUMNS
    WHERE
        TABLE_NAME = tablename
    AND
        COLUMN_NAME = colname
    AND
        TABLE_SCHEMA = dbname;

    RETURN retval;
END

你可以像这样使用它:

$stmt = $pdo->prepare("
  INSERT INTO
    foo
    (x,y,z)
  VALUES
    (
      Coalesce(:x, NULLDEFAULT('x', 'foo', 'database')),
      Coalesce(:y, NULLDEFAULT('y', 'foo', 'database')),
      Coalesce(:z, NULLDEFAULT('z', 'foo', 'database'))
    )
");

如果列没有默认值,则将返回 null,并且不会触发“列没有默认值”错误

当然您可以将其修改为不需要数据库参数。

I tried replying to VolkerK answer, but couldnt find how. :( I'm kinda new to all this.

Anyway, I created a mysql function to use in conjuction with his COALESCE idea

CREATE FUNCTION NULLDEFAULT(colname VARCHAR(64), tablename VARCHAR(64), dbname VARCHAR(64)) RETURNS longtext DETERMINISTIC READS SQL DATA
BEGIN
    DECLARE retval longtext;
    SELECT
        COLUMN_DEFAULT INTO retval 
    FROM
        information_schema.COLUMNS
    WHERE
        TABLE_NAME = tablename
    AND
        COLUMN_NAME = colname
    AND
        TABLE_SCHEMA = dbname;

    RETURN retval;
END

You would use it like this:

$stmt = $pdo->prepare("
  INSERT INTO
    foo
    (x,y,z)
  VALUES
    (
      Coalesce(:x, NULLDEFAULT('x', 'foo', 'database')),
      Coalesce(:y, NULLDEFAULT('y', 'foo', 'database')),
      Coalesce(:z, NULLDEFAULT('z', 'foo', 'database'))
    )
");

That will return null if the column has no default value, and won't trigger the "Column has no default value" Error.

Of course you could modify it to not require the database parameter

人事已非 2024-09-01 22:42:37

尝试改变这个:

$statement = $pdoObject->
    prepare("INSERT INTO table1 (column1,column2) values (?,?)");
$statement->execute(array('value1','DEFAULT'));

对此:

$statement = $pdoObject->
    prepare("INSERT INTO table1 (column1,column2) values (?,DEFAULT)");
$statement->execute(array('value1'));

在我看来,你的原始代码会给你这个:

INSERT INTO table1 (column1,column2) values ('value1','DEFAULT')

我的代码应该给你这个:

INSERT INTO table1 (column1,column2) values ('value1',DEFAULT)

Try changing this:

$statement = $pdoObject->
    prepare("INSERT INTO table1 (column1,column2) values (?,?)");
$statement->execute(array('value1','DEFAULT'));

To this:

$statement = $pdoObject->
    prepare("INSERT INTO table1 (column1,column2) values (?,DEFAULT)");
$statement->execute(array('value1'));

It seems to me that your original code will give you this:

INSERT INTO table1 (column1,column2) values ('value1','DEFAULT')

My code should give you this:

INSERT INTO table1 (column1,column2) values ('value1',DEFAULT)
不离久伴 2024-09-01 22:42:37

我认为它正在写入字符串“DEFAULT”,因为它是由 pdo 转义的,因此有用于绑定值的参数,您可以在其中指定给定值的类型,以便您可以发送不带引号的空值,它将是 PDO::PARAM_NULL ;然后将输入默认值,但我不确定与execute绑定时是否有类似的参数

  if(is_int($param)){$pdoParam = PDO::PARAM_INT;}
      elseif(is_bool($param)){$pdoParam = PDO::PARAM_BOOL;}
      elseif(is_null($param)){ $pdoParam = PDO::PARAM_NULL;}
      elseif(is_string($param)){$pdoParam = PDO::PARAM_STR;}
                                    else{$pdoParam = FALSE;}
              $this->_query->bindValue($k,$param,$pdoParam);

i think that it is writing the String 'DEFAULT ' because it is escaped by pdo so there are parametres for bindvalue where you can specify the type of the value given so you can send a null with no quotes and it will be PDO::PARAM_NULL; and then default values will be put , but i'm not sure if there are similar parameters when binding with execute

  if(is_int($param)){$pdoParam = PDO::PARAM_INT;}
      elseif(is_bool($param)){$pdoParam = PDO::PARAM_BOOL;}
      elseif(is_null($param)){ $pdoParam = PDO::PARAM_NULL;}
      elseif(is_string($param)){$pdoParam = PDO::PARAM_STR;}
                                    else{$pdoParam = FALSE;}
              $this->_query->bindValue($k,$param,$pdoParam);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文