2010-03-17 8 views
15

Trích dẫn MySQL INSERT thủ công - Cũng vậy với UPDATE:Chuẩn bị một tuyên bố/UPDATE MySQL INSERT với giá trị DEFAULT

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.

Vì vậy, trong ngắn hạn nếu tôi viết

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

Một hàng mới với column2 thiết lập như giá trị mặc định của nó - bất kỳ giá trị nào có thể - được chèn vào.

Tuy nhiên nếu tôi chuẩn bị và thực hiện một tuyên bố trong PHP:

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

Hàng mới sẽ chứa 'DEFAULT' như giá trị văn bản của nó - nếu cột có khả năng lưu trữ các giá trị văn bản.

Bây giờ tôi đã viết một lớp trừu tượng để PDO (Tôi cần nó) và để có được xung quanh vấn đề này đang xem xét để đưa ra một

const DEFAULT_VALUE = "randomstring"; 

Vì vậy, tôi có thể thực hiện báo cáo như thế này:

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

Và sau đó trong phương pháp mà không ràng buộc tôi đi qua các giá trị được gửi đến bị ràng buộc và nếu một số là tương đương với self::DEFAULT_VALUE, hành động phù hợp.

Tôi chắc chắn có cách tốt hơn để thực hiện việc này. Có ai khác gặp phải tình huống tương tự không?

+0

Vì PDO đang xử lý giá trị của bạn dưới dạng chuỗi để nhập, có vẻ như bạn có thể phải thay đổi mã một chút, nếu có thể. Bạn có thể thay đổi nó để bạn gõ '... execute (array ('\' value1 \ '', 'DEFAULT'))', nhưng tôi đoán PDO đang xử lý các giá trị này cho bạn với 'mysql_real_escape_string() ', vv Điều này sẽ đánh bại chức năng đó. Bạn có lẽ sẽ phải chèn trực tiếp nó vào đối số 'prepare()'. – Jonah

+1

Tại sao không chỉ bao gồm các cột trong câu lệnh 'INSERT' mà bạn đang đặt thành một giá trị khác với giá trị mặc định? –

+1

Vấn đề là với 'UPDATE' và một đầu vào được gửi trống. Tôi cần nó là một mặc định, không ví dụ '0000-00-00' cho các trường ngày khi '' '' được đặt làm giá trị mới. – raveren

Trả lời

8

Các chỉ "workaround" Tôi biết cho điều này là sử dụng Coalesce()Default(fieldname)

Ví dụ:

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

in

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

Mặc định (x) có thể là DEFAULT, không cần phải đề cập đến tên cột nếu bạn muốn giá trị mặc định cho cột này trong cùng một cột. Đó là lỗi. CẬP NHẬT t SET x = DEFAULT; –

+0

Suy nghĩ tuyệt vời! Không hoàn hảo nhưng đánh bại giải pháp của tôi! – raveren

+3

@Frank: Nó phải là Mặc định (tên trường) khi được sử dụng làm đối số cho Coalesce(). – VolkerK

0

Hãy thử thay đổi này:

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

Để này:

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

Dường như với tôi rằng mã ban đầu của bạn sẽ cung cấp cho bạn điều này:

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

Mã của tôi sẽ cho bạn này:

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

Ai có thể muốn các giá trị khác nhưng vẫn mặc định. – raveren

1

Tôi cố gắng trả lời VolkerK câu trả lời, nhưng couldnt tìm thấy như thế nào. :(Tôi kinda mới để tất cả điều này

Dù sao, tôi tạo ra một hàm mysql để sử dụng trong conjuction với ý tưởng liên hiệp của ông

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 

Bạn sẽ sử dụng nó như thế này:.

$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')) 
    ) 
"); 

Điều đó sẽ trả về null nếu cột không có giá trị mặc định và sẽ không kích hoạt lỗi "Cột không có giá trị mặc định".

Tất nhiên bạn có thể sửa đổi nó để không yêu cầu các tham số cơ sở dữ liệu

+0

Tôi không nghĩ rằng nó sẽ giữ hiệu suất khôn ngoan. AFAIK mysql sẽ không lưu trữ kết quả của các hàm, vì vậy bạn sẽ gọi truy vấn của bạn cho mỗi hàng và mỗi cột trong truy vấn chèn. Tốt hơn hết là nên lấy các giá trị mặc định qua PHP trước, nhưng như tôi đã kết luận, bài học của tôi ở đây là không được tính vào các giá trị mysql mặc định. Tôi vẫn sẽ cung cấp cho bạn một +1 cho nỗ lực này. – raveren

+0

Theo tài liệu, từ khóa DETERMINISTIC cho mysql biết rằng hàm luôn trả về cùng các giá trị với cùng các tham số, do đó sẽ dẫn tôi tin rằng nó sẽ lưu lại kết quả. Nhưng tôi đã không nếm trải nó rộng rãi, tôi đang sử dụng nó trong một mạng nội bộ nhỏ mà không giảm tốc độ đáng chú ý. –

0

tôi nghĩ rằng nó được viết String 'DEFAULT' bởi vì nó được thoát bởi PDO để có parametres cho bindvalue nơi bạn có thể chỉ định các loại giá trị được đưa ra để bạn có thể gửi một null không có dấu ngoặc kép và nó sẽ là PDO :: PARAM_NULL; và sau đó giá trị mặc định sẽ được đặt, nhưng tôi không chắc liệu có các tham số tương tự khi ràng buộc với thực thi

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

Có gì '$ pdoParam = FALSE;' phải đạt được? Giá trị mặc định là 'PARAM_STR'. – DanMan