Подготовка оператора MySQL INSERT/UPDATE со Значениями по умолчанию

MySQL Quoting ВСТАВЛЯЕТ руководство - то же идет для ОБНОВЛЕНИЯ:

Используйте ЗНАЧЕНИЕ ПО УМОЛЧАНИЮ ключевого слова для установки столбца явно на его значение по умолчанию. Это помогает записать операторы INSERT, которые присваивают значения всем кроме нескольких столбцов, потому что это позволяет Вам постараться не написать неполный список ЗНАЧЕНИЙ, который не включает значение для каждого столбца в таблице. Иначе необходимо было бы выписать список имен столбцов, соответствующих каждому значению в списке ЗНАЧЕНИЙ.

Так короче говоря, если я пишу

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

Вставляется новая строка с набором column2 как его значение по умолчанию - независимо от того, что это может быть-.

Однако, если я готовлю и выполняю оператор в PHP:

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

Новая строка будет содержать 'ЗНАЧЕНИЕ ПО УМОЛЧАНИЮ' как свое текстовое значение - если столбец сможет сохранить текстовые значения.

Теперь я записал уровень абстракции в PDO (мне был нужен он), и обойти эту проблему рассматривает для представления a

const DEFAULT_VALUE = "randomstring";

Таким образом, я мог выполнить операторы как это:

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

И затем в методе, который делает привязку, я прошел бы значения, которые отправляются, чтобы быть связанными и если некоторые равны self::DEFAULT_VALUE, действуйте соответственно.

Я вполне уверен существует лучший способ сделать это. Кто-то еще встретился с аналогичными ситуациями?

15
задан raveren 17 March 2010 в 18:13
поделиться

3 ответа

Единственное известное мне «обходное решение» - использовать Coalesce () и Default (fieldname)

Например

$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";
}

print

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
8
ответ дан 1 December 2019 в 05:02
поделиться

Попробуйте изменить это:

$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)
0
ответ дан 1 December 2019 в 05:02
поделиться

Я пытался ответить на ответ 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, если колонка не имеет значения по умолчанию, и не вызовет ошибку "Column has no default value".

Конечно, вы можете изменить его так, чтобы он не требовал параметра базы данных

1
ответ дан 1 December 2019 в 05:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: