Подготовка оператора MySQL INSERT / UPDATE со значениями DEFAULT - PullRequest
15 голосов
/ 17 марта 2010

Цитирование инструкции 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'));

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

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

const DEFAULT_VALUE = "randomstring";

Так что я мог бы выполнять операторы так:

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

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

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

Ответы [ 4 ]

8 голосов
/ 18 марта 2010

Единственный «обходной путь», который я знаю для этого, - это использование Coalesce () и По умолчанию (имя поля)

1007 * Е.Г. *

$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
1 голос
/ 26 марта 2010

Я пытался ответить на ответ 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'))
    )
");

Возвращает ноль, если столбец не имеет значения по умолчанию, и не вызывает ошибку «Столбец не имеет значения по умолчанию».

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

0 голосов
/ 17 октября 2013

я думаю, что он записывает строку '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);
0 голосов
/ 17 марта 2010

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

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