Подготовка инструкции MySQL INSERT/UPDATE с значениями DEFAULT
Цитата: Руководство MySQL INSERT - то же самое для UPDATE:
Используйте ключевое слово DEFAULT, чтобы явно указать значение столбца по умолчанию. Это упрощает запись инструкций INSERT, которые присваивают значения всем, кроме нескольких столбцов, потому что это позволяет избежать записи неполного списка VALUES, который не включает значение для каждого столбца в таблице. В противном случае вам нужно будет записать список имен столбцов, соответствующих каждому значению в списке VALUES.
Короче, если я пишу
INSERT INTO table1 (column1,column2) values ('value1',DEFAULT);
Вставляется новая строка с столбцом2, установленная как значение по умолчанию - независимо от того, что она может быть.
Однако, если я готовлю и выполняю инструкцию в 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));
И затем в методе, который выполняет привязку, я бы прошел через значения, которые отправляются для привязки, и если некоторые из них равны self::DEFAULT_VALUE
, действуйте соответственно.
Я уверен, что есть лучший способ сделать это. Кто-то еще сталкивался с подобными ситуациями?
Ответы
Ответ 1
Единственным "обходным решением", которое я знаю для этого, является использование 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
Ответ 2
Я попытался ответить на ответ 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, если столбец не имеет значения по умолчанию, и не будет запускать "Столбец не имеет значения по умолчанию".
Конечно, вы можете изменить его, чтобы не требовать параметр базы данных
Ответ 3
Попробуйте изменить это:
$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)
Ответ 4
Я думаю, что он пишет String 'DEFAULT', потому что он экранирован pdo, поэтому есть параметры для bindvalue, где вы можете указать тип заданного значения, чтобы вы могли отправить нуль без кавычек, и это будет 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);