Подготовка инструкции MySQL INSERT / UPDATE с значениями DEFAULT

Цитата MySQL INSERT manual – то же самое для 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 , действуйте соответствующим образом.

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

Единственный «обходной путь», который я знаю для этого, – использовать 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"; } с $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 

Я попытался ответить на ответ 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, если столбец не имеет значения по умолчанию, и не будет вызывать «Ошибка столбца не имеет значения по умолчанию».

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

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

 $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) 

Я думаю, что он пишет String 'DEFAULT', потому что он экранирован pdo, поэтому есть параметры для bindvalue, где вы можете указать тип заданного значения, чтобы вы могли отправить нуль без кавычек, и это будет PDO :: PARAM_NULL ; а затем будут заданы значения по умолчанию, но я не уверен, есть ли аналогичные параметры при связывании с выполнением

  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);