Nhiều cập nhật trong MySQL


388

Tôi biết rằng bạn có thể chèn nhiều hàng cùng một lúc, có cách nào để cập nhật nhiều hàng cùng một lúc (như trong một truy vấn) trong MySQL không?

Chỉnh sửa: Ví dụ tôi có những điều sau đây

Name   id  Col1  Col2
Row1   1    6     1
Row2   2    2     3
Row3   3    9     5
Row4   4    16    8

Tôi muốn kết hợp tất cả các Cập nhật sau vào một truy vấn

UPDATE table SET Col1 = 1 WHERE id = 1;
UPDATE table SET Col1 = 2 WHERE id = 2;
UPDATE table SET Col2 = 3 WHERE id = 3;
UPDATE table SET Col1 = 10 WHERE id = 4;
UPDATE table SET Col2 = 12 WHERE id = 4;

Câu trả lời:


651

Có, điều đó là có thể - bạn có thể sử dụng CHERTN ... TRÊN CẬP NHẬT TỪ KHÓA.

Sử dụng ví dụ của bạn:

INSERT INTO table (id,Col1,Col2) VALUES (1,1,1),(2,2,3),(3,9,3),(4,10,12)
ON DUPLICATE KEY UPDATE Col1=VALUES(Col1),Col2=VALUES(Col2);

22
Nếu không có trùng lặp thì tôi không muốn hàng đó được chèn vào. id nên làm gì? bởi vì tôi đang tìm nạp thông tin từ một trang web khác duy trì các bảng có id. Tôi đang chèn các giá trị liên quan đến id đó. Nếu trang web có hồ sơ mới thì cuối cùng tôi sẽ chỉ chèn id và đếm trừ tất cả các thông tin khác. Nếu và chỉ khi có một mục nhập cho id thì nó nên cập nhật khác, nó sẽ bỏ qua. tôi nên làm gì?
Jayapal Chandran

33
Lưu ý: câu trả lời này cũng cho rằng ID là khóa chính
JM4

11
@JayapalChandran bạn nên sử dụng INSERT IGNORE cùng với CẬP NHẬT KHÓA NGHIÊM TRỌNG. dev.mysql.com/doc/refman/5.5/en/insert.html
Haralan Dobrev

16
@HaralanDobrev Sử dụng INSERT IGNORE vẫn chèn các bản ghi không trùng lặp. Điều mà Jayapal muốn tránh. CHERTN IGNORE chỉ biến bất kỳ lỗi nào thành cảnh báo :( stackoverflow.com/questions/548541/iêu
Takehiro Adachi

2
Câu trả lời này giả sử ID là một khóa duy nhất (có thể là chính như những người khác đã nói) nhưng quan trọng hơn là nó giả định không có khóa duy nhất nào khác. Nếu có, nó có thể ném cờ lê vào công trình.
Steve Horvath

129

Vì bạn có các giá trị động, bạn cần sử dụng IF hoặc CASE cho các cột được cập nhật. Nó trở nên xấu xí, nhưng nó nên hoạt động.

Sử dụng ví dụ của bạn, bạn có thể làm như sau:

Bảng CẬP NHẬT SET Col1 = id CASE 
                          KHI 1 THÌ 1 
                          KHI 2 THÌ 2 
                          KHI 4 THÌ 10 
                          ELSE Col1 
                        KẾT THÚC, 
                 Col2 = id CASE 
                          KHI 3 THÌ 3 
                          KHI 4 THÁNG 12 
                          ELSE Col2 
                        KẾT THÚC
             Id Ở ĐÂU (1, 2, 3, 4);

có thể không đẹp lắm để viết cho cập nhật động nhưng cái nhìn thú vị về chức năng của vỏ ...
me_

1
@ user2536953, nó cũng có thể tốt cho việc cập nhật động. Ví dụ: tôi đã sử dụng giải pháp đó trong vòng lặp trong php:$commandTxt = 'UPDATE operations SET chunk_finished = CASE id '; foreach ($blockOperationChecked as $operationID => $operationChecked) $commandTxt .= " WHEN $operationID THEN $operationChecked "; $commandTxt .= 'ELSE id END WHERE id IN ('.implode(', ', array_keys(blockOperationChecked )).');';
Boolean_Type

86

Câu hỏi đã cũ, nhưng tôi muốn mở rộng chủ đề bằng một câu trả lời khác.

Quan điểm của tôi là, cách dễ nhất để đạt được nó chỉ là bọc nhiều truy vấn với một giao dịch. Câu trả lời được chấp nhận INSERT ... ON DUPLICATE KEY UPDATElà một bản hack hay, nhưng người ta nên nhận thức được những hạn chế và hạn chế của nó:

  • Như đã nói, nếu bạn tình cờ khởi chạy truy vấn với các hàng có khóa chính không tồn tại trong bảng, thì truy vấn sẽ chèn các bản ghi "nửa nướng" mới. Có lẽ đó không phải là điều bạn muốn
  • Nếu bạn có một bảng có trường không null không có giá trị mặc định và không muốn chạm vào trường này trong truy vấn, bạn sẽ nhận được "Field 'fieldname' doesn't have a default value"cảnh báo MySQL ngay cả khi bạn không chèn một hàng nào cả. Nó sẽ khiến bạn gặp rắc rối, nếu bạn quyết định nghiêm khắc và biến cảnh báo mysql thành ngoại lệ thời gian chạy trong ứng dụng của bạn.

Tôi đã thực hiện một số thử nghiệm hiệu suất cho ba trong số các biến thể được đề xuất, bao gồm INSERT ... ON DUPLICATE KEY UPDATEbiến thể, một biến thể với mệnh đề "trường hợp / khi / sau đó" và một cách tiếp cận ngây thơ với giao dịch. Bạn có thể nhận được mã python và kết quả ở đây . Kết luận chung là biến thể với tuyên bố trường hợp hóa ra nhanh gấp đôi so với hai biến thể khác, nhưng khá khó để viết mã chính xác và an toàn cho nó, vì vậy cá nhân tôi tuân theo cách tiếp cận đơn giản nhất: sử dụng giao dịch.

Chỉnh sửa: Kết quả của Dakusan chứng minh rằng ước tính hiệu suất của tôi không hoàn toàn hợp lệ. Xin vui lòng xem câu trả lời này cho một nghiên cứu khác, công phu hơn.


Sử dụng giao dịch, mẹo rất hay (và đơn giản)!
mTorres

Điều gì xảy ra nếu các bảng của tôi không phải là Loại InnoDB?
TomeeNS

1
Ai đó có thể cung cấp một liên kết đến những giao dịch để làm điều này trông như thế nào? Và / hoặc mã cho một mã an toàn tiêm cho biến thể với tuyên bố trường hợp?
François M.

1
Tôi thấy thông tin được đưa ra về tốc độ trong bài này là sai. Tôi đã viết về nó trong một bài viết dưới đây. stackoverflow.com/questions
43232 / mult Môn

1
@Dakusan, câu trả lời tuyệt vời. Cảm ơn rất nhiều vì đã mở rộng, bình luận và sửa chữa kết quả của tôi.
Roman Imankulov

72

Không chắc chắn tại sao một tùy chọn hữu ích khác chưa được đề cập:

UPDATE my_table m
JOIN (
    SELECT 1 as id, 10 as _col1, 20 as _col2
    UNION ALL
    SELECT 2, 5, 10
    UNION ALL
    SELECT 3, 15, 30
) vals ON m.id = vals.id
SET col1 = _col1, col2 = _col2;

4
Đây là thứ tốt nhất. Đặc biệt nếu bạn đang lấy các giá trị để cập nhật từ một truy vấn SQL khác như tôi đang làm.
v010dya

1
Điều này thật tuyệt vời cho một bản cập nhật trên một bảng với số lượng lớn các cột. Tôi có thể sẽ sử dụng truy vấn này rất nhiều trong tương lai. Cảm ơn!
Casper Wilkes

Tôi đã thử loại truy vấn này. Nhưng khi hồ sơ đạt 30k Máy chủ Ranh giới dừng lại. Còn có những giải pháp nào nữa ko?
Bhavin Chauhan

Điều này có vẻ tuyệt vời. Tôi sẽ thử kết hợp điều này với mệnh đề WHERE trong đó các khóa chính không được cập nhật, nhưng được sử dụng để xác định các cột cần thay đổi.
nl-x

@BhavinChauhan Bạn đã thử sử dụng bảng tạm thời thay vì chọn tham gia để tránh sự cố chưa?
nl-x

41

Tất cả những điều sau đây áp dụng cho InnoDB.

Tôi cảm thấy biết tốc độ của 3 phương pháp khác nhau là quan trọng.

Có 3 phương pháp:

  1. XÁC NHẬN: XÁC NHẬN VỚI CẬP NHẬT TỪ KHÓA
  2. GIAO DỊCH: Nơi bạn thực hiện cập nhật cho mỗi bản ghi trong một giao dịch
  3. TRƯỜNG HỢP: Trong đó bạn là một trường hợp / khi cho mỗi bản ghi khác nhau trong một CẬP NHẬT

Tôi mới thử nghiệm điều này và phương pháp INSERT là 6,7 lần nhanh hơn lần so với phương thức GIAO DỊCH. Tôi đã thử trên một bộ gồm cả 3.000 và 30.000 hàng.

Phương thức TRANSACTION vẫn phải chạy từng truy vấn riêng lẻ, điều này sẽ mất thời gian, mặc dù nó bó các kết quả trong bộ nhớ hoặc một cái gì đó trong khi thực hiện. Phương thức TRANSACTION cũng khá tốn kém trong cả bản ghi truy vấn và sao chép.

Tệ hơn nữa, phương pháp CASE là 41,1 lần chậm hơn so với phương pháp INSERT w / 30.000 bản ghi (chậm hơn 6,1 lần so với GIAO DỊCH). Và chậm hơn 75 lần trong MyISAM. Phương pháp INSERT và CASE đã phá vỡ thậm chí ở mức ~ 1.000 hồ sơ. Ngay cả ở 100 bản ghi, phương pháp CASE vẫn nhanh hơn.

Vì vậy, nói chung, tôi cảm thấy phương pháp INSERT là tốt nhất và dễ sử dụng nhất. Các truy vấn nhỏ hơn và dễ đọc hơn và chỉ chiếm 1 truy vấn hành động. Điều này áp dụng cho cả InnoDB và MyISAM.

Phần thưởng:

Giải pháp cho vấn đề không phải trường mặc định của INSERT là tạm thời tắt các chế độ SQL có liên quan : SET SESSION sql_mode=REPLACE(REPLACE(@@SESSION.sql_mode,"STRICT_TRANS_TABLES",""),"STRICT_ALL_TABLES",""). Hãy chắc chắn để lưu sql_modeđầu tiên nếu bạn có kế hoạch hoàn nguyên nó.

Đối với các bình luận khác mà tôi đã thấy nói rằng auto_increment tăng lên khi sử dụng phương thức INSERT, điều này dường như là trường hợp trong InnoDB, nhưng không phải là MyISAM.

Mã để chạy các bài kiểm tra như sau. Nó cũng xuất ra các tệp .Query để loại bỏ trình thông dịch php

<?
//Variables
$NumRows=30000;

//These 2 functions need to be filled in
function InitSQL()
{

}
function RunSQLQuery($Q)
{

}

//Run the 3 tests
InitSQL();
for($i=0;$i<3;$i++)
    RunTest($i, $NumRows);

function RunTest($TestNum, $NumRows)
{
    $TheQueries=Array();
    $DoQuery=function($Query) use (&$TheQueries)
    {
        RunSQLQuery($Query);
        $TheQueries[]=$Query;
    };

    $TableName='Test';
    $DoQuery('DROP TABLE IF EXISTS '.$TableName);
    $DoQuery('CREATE TABLE '.$TableName.' (i1 int NOT NULL AUTO_INCREMENT, i2 int NOT NULL, primary key (i1)) ENGINE=InnoDB');
    $DoQuery('INSERT INTO '.$TableName.' (i2) VALUES ('.implode('), (', range(2, $NumRows+1)).')');

    if($TestNum==0)
    {
        $TestName='Transaction';
        $Start=microtime(true);
        $DoQuery('START TRANSACTION');
        for($i=1;$i<=$NumRows;$i++)
            $DoQuery('UPDATE '.$TableName.' SET i2='.(($i+5)*1000).' WHERE i1='.$i);
        $DoQuery('COMMIT');
    }

    if($TestNum==1)
    {
        $TestName='Insert';
        $Query=Array();
        for($i=1;$i<=$NumRows;$i++)
            $Query[]=sprintf("(%d,%d)", $i, (($i+5)*1000));
        $Start=microtime(true);
        $DoQuery('INSERT INTO '.$TableName.' VALUES '.implode(', ', $Query).' ON DUPLICATE KEY UPDATE i2=VALUES(i2)');
    }

    if($TestNum==2)
    {
        $TestName='Case';
        $Query=Array();
        for($i=1;$i<=$NumRows;$i++)
            $Query[]=sprintf('WHEN %d THEN %d', $i, (($i+5)*1000));
        $Start=microtime(true);
        $DoQuery("UPDATE $TableName SET i2=CASE i1\n".implode("\n", $Query)."\nEND\nWHERE i1 IN (".implode(',', range(1, $NumRows)).')');
    }

    print "$TestName: ".(microtime(true)-$Start)."<br>\n";

    file_put_contents("./$TestName.sql", implode(";\n", $TheQueries).';');
}

1
Bạn đang làm công việc của Chúa ở đây;) Được đánh giá cao.
ớt

Thử nghiệm một số hiệu suất giữa GoLang và PHP, sử dụng 40 nghìn hàng trên MariaDB, tôi đã nhận được 2 giây trên PHP và hơn 6 giây trên golang .... Chà, tôi luôn được thông báo rằng GoLang sẽ chạy nhanh hơn PHP !!! VÌ VẬY, tôi bắt đầu tự hỏi làm thế nào để cải thiện hiệu suất ... Sử dụng CHERTN ... TRÊN CẬP NHẬT KHÓA NGHIÊM TRỌNG ... Tôi đã nhận được 0,74 giây trên Golang và 0,86 giây trên PHP !!!!
Diego Favero

1
Điểm quan trọng của mã của tôi là giới hạn kết quả định thời theo các câu lệnh SQL và không phải là mã cho ngôn ngữ hoặc thư viện. GoLang và PHP là 2 ngôn ngữ hoàn toàn riêng biệt dành cho những thứ hoàn toàn khác nhau. PHP có nghĩa là cho một môi trường tập lệnh chạy đơn trên một luồng với bộ sưu tập rác bị hạn chế và bị động. GoLang có nghĩa là cho các ứng dụng được biên dịch chạy dài với bộ sưu tập rác tích cực và đa luồng là một trong những tính năng ngôn ngữ chính. Họ hầu như không thể khác biệt hơn về chức năng ngôn ngữ và lý do. [Tiếp tục]
Dakusan

Vì vậy, khi chạy các bài kiểm tra của bạn, hãy đảm bảo giới hạn các phép đo tốc độ theo đúng chức năng "Truy vấn" cho câu lệnh SQL. So sánh và tối ưu hóa các phần khác của mã nguồn không hoàn toàn là cuộc gọi truy vấn giống như so sánh táo và cam. Nếu bạn giới hạn kết quả của mình ở mức này (có các chuỗi được biên dịch trước và sẵn sàng hoạt động) thì kết quả sẽ rất giống nhau. Bất kỳ sự khác biệt nào tại thời điểm đó là lỗi của thư viện SQL của ngôn ngữ và không nhất thiết phải là ngôn ngữ. Theo tôi, giải pháp INSERT ON DUPLICATE đã và sẽ luôn là lựa chọn tốt nhất. [Tiếp]
Dakusan

Đối với nhận xét của bạn về GoLang nhanh hơn, đó là một tuyên bố cực kỳ rộng rãi không tính đến bất kỳ sự cảnh giác hay sắc thái nào của các ngôn ngữ này và thiết kế của chúng. Java là một ngôn ngữ được giải thích, nhưng tôi phát hiện ra 15 năm trước nó thực sự có thể khớp với (và thậm chí đôi khi có thể đánh bại) C về tốc độ trong một số tình huống nhất định. Và C là một ngôn ngữ được biên dịch và là ngôn ngữ hệ thống cấp thấp nhất, bên cạnh trình biên dịch. Tôi thực sự yêu thích những gì GoLang đang làm và nó chắc chắn có sức mạnh và sự linh hoạt để trở thành một trong những hệ thống phổ biến nhất và được tối ưu hóa [Tiếp]
Dakusan

9

Sử dụng bảng tạm thời

// Reorder items
function update_items_tempdb(&$items)
{
    shuffle($items);
    $table_name = uniqid('tmp_test_');
    $sql = "CREATE TEMPORARY TABLE `$table_name` ("
        ."  `id` int(10) unsigned NOT NULL AUTO_INCREMENT"
        .", `position` int(10) unsigned NOT NULL"
        .", PRIMARY KEY (`id`)"
        .") ENGINE = MEMORY";
    query($sql);
    $i = 0;
    $sql = '';
    foreach ($items as &$item)
    {
        $item->position = $i++;
        $sql .= ($sql ? ', ' : '')."({$item->id}, {$item->position})";
    }
    if ($sql)
    {
        query("INSERT INTO `$table_name` (id, position) VALUES $sql");
        $sql = "UPDATE `test`, `$table_name` SET `test`.position = `$table_name`.position"
            ." WHERE `$table_name`.id = `test`.id";
        query($sql);
    }
    query("DROP TABLE `$table_name`");
}

8
UPDATE table1, table2 SET table1.col1='value', table2.col1='value' WHERE table1.col3='567' AND table2.col6='567'

Điều này sẽ làm việc cho ya.

Có một tài liệu tham khảo trong hướng dẫn sử dụng MySQL cho nhiều bảng.


6

Tại sao không ai đề cập đến nhiều câu trong một truy vấn ?

Trong php, bạn sử dụng multi_queryphương thức mysqli dụ.

Từ hướng dẫn sử dụng php

MySQL tùy chọn cho phép có nhiều câu lệnh trong một chuỗi câu lệnh. Gửi nhiều báo cáo cùng một lúc làm giảm các chuyến đi khứ hồi giữa máy khách và máy chủ nhưng cần xử lý đặc biệt.

Đây là kết quả so với 3 phương pháp khác trong bản cập nhật 30.000 nguyên. Mã có thể được tìm thấy ở đây dựa trên câu trả lời từ @Dakusan

Giao dịch: 5.5194580554962
Chèn: 0.20669293403625
Vỏ: 16.474853992462
Đa: 0.0412278175354

Như bạn có thể thấy, nhiều câu truy vấn hiệu quả hơn câu trả lời cao nhất.

Nếu bạn nhận được thông báo lỗi như thế này:

PHP Warning:  Error while sending SET_OPTION packet

Bạn có thể cần tăng max_allowed_packettệp cấu hình mysql trong máy của tôi /etc/mysql/my.cnfvà sau đó khởi động lại mysqld.


Tất cả các so sánh dưới đây được chạy với thử nghiệm INSERT. Tôi chỉ chạy thử nghiệm trong cùng điều kiện và, không có giao dịch, nó chậm hơn 145 lần trên 300 hàng và chậm hơn 753x cho 3000 hàng. Ban đầu tôi đã bắt đầu với 30.000 hàng, nhưng tôi đã tự làm bữa trưa và quay lại và nó vẫn tiếp tục. Điều này có ý nghĩa khi chạy các truy vấn riêng lẻ và xóa từng truy vấn vào cơ sở dữ liệu riêng lẻ sẽ rất tốn kém. Đặc biệt là với sự nhân rộng. Bật giao dịch mặc dù tạo ra một sự khác biệt lớn. Tại 3.000 hàng, mất thêm 1,5 lần và tại 30.000 hàng 2,34 lần . [tiếp tục]
Dakusan

Nhưng bạn đã đúng về nó là nhanh chóng (với các giao dịch). Ở cả 3.000 và 30.000 hàng, nó nhanh hơn tất cả mọi thứ trừ phương thức INSERT. Hoàn toàn không có cách nào bạn sẽ có được kết quả tốt hơn khi chạy 1 truy vấn hơn 30.000 truy vấn, ngay cả khi chúng được bó trong một lệnh gọi API MySQL đặc biệt. Chỉ chạy 300 hàng, nó NHIỀU nhanh hơn tất cả các phương thức khác (làm tôi ngạc nhiên), theo sau về đường cong đồ thị tương tự như phương pháp CASE. Điều này nhanh hơn có thể được giải thích bằng 2 cách. Đầu tiên là phương thức INSERT về cơ bản luôn chèn 2 hàng do "KHÓA
KHAI THÁC

CẬP NHẬT "gây ra cả" CHERTN "và" CẬP NHẬT ". Một điều nữa là bộ xử lý SQL ít hoạt động hơn khi chỉ chỉnh sửa 1 hàng mỗi lần do tra cứu chỉ mục. Tôi không chắc bạn có kết quả khác với tôi như thế nào nhưng thử nghiệm bổ sung của bạn có vẻ chắc chắn. Tôi thực sự thậm chí không chắc cách sao chép sẽ xử lý cuộc gọi này. Điều này cũng chỉ hoạt động để thực hiện các cuộc gọi CẬP NHẬT. Các cuộc gọi chèn sẽ LUÔN nhanh nhất với truy vấn INSERT duy nhất.
Dakusan

Tôi đã thực hiện 300 CẬP NHẬT tại một thời điểm trên một bảng để sửa lỗi trong vòng lặp for mất 41 giây. Đặt các truy vấn CẬP NHẬT tương tự vào một $mysqli->multi_query($sql)mất "0" giây. Tuy nhiên, các truy vấn tiếp theo không thành công, khiến tôi biến đây thành một "chương trình" riêng biệt.
Chris K

Cảm ơn. Đã có thể cập nhật khoảng 5k hàng (không kiểm tra thêm) trong một phút bằng nhiều truy vấn. Nếu ai đó đang tìm kiếm giải pháp PDO: stackoverflow.com/questions/6346674/ cấp
Scofield

3

Có một cài đặt mà bạn có thể thay đổi được gọi là 'đa tuyên bố' vô hiệu hóa 'cơ chế an toàn' của MySQL được triển khai để ngăn chặn (nhiều hơn một) lệnh tiêm. Điển hình cho việc triển khai 'xuất sắc' của MySQL, nó cũng ngăn người dùng thực hiện các truy vấn hiệu quả.

Ở đây ( http://dev.mysql.com/doc/refman/5.1/en/mysql-set-server-option.html ) là một số thông tin về việc triển khai C của cài đặt.

Nếu bạn đang sử dụng PHP, bạn có thể sử dụng mysqli để thực hiện nhiều câu lệnh (Tôi nghĩ rằng php đã xuất xưởng với mysqli trong một thời gian rồi)

$con = new mysqli('localhost','user1','password','my_database');
$query = "Update MyTable SET col1='some value' WHERE id=1 LIMIT 1;";
$query .= "UPDATE MyTable SET col1='other value' WHERE id=2 LIMIT 1;";
//etc
$con->multi_query($query);
$con->close();

Mong rằng sẽ giúp.


4
Điều này giống như gửi các truy vấn riêng. Sự khác biệt duy nhất là bạn gửi tất cả trong một gói mạng, nhưng các CẬP NHẬT sẽ vẫn được xử lý dưới dạng các truy vấn riêng biệt. Tốt hơn là bọc chúng trong một giao dịch, sau đó các thay đổi sẽ được đưa vào bảng cùng một lúc.
Marki555

3
Làm thế nào để bọc chúng trong một giao dịch? Cho chúng tôi xem
TomeeNS

@TomeeNS Sử dụng mysqli::begin_transaction(..)trước khi gửi truy vấn và mysql::commit(..)sau đó. Hoặc sử dụng START TRANSACTIONnhư COMMITcâu lệnh đầu tiên và cuối cùng trong chính truy vấn.
Juha Palomäki

3

Bạn có thể đặt bí danh cho cùng một bảng để cung cấp cho bạn id mà bạn muốn chèn theo (nếu bạn đang thực hiện cập nhật theo từng hàng:

UPDATE table1 tab1, table1 tab2 -- alias references the same table
SET 
col1 = 1
,col2 = 2
. . . 
WHERE 
tab1.id = tab2.id;

Ngoài ra, có vẻ như rõ ràng là bạn cũng có thể cập nhật từ các bảng khác. Trong trường hợp này, bản cập nhật nhân đôi thành một câu lệnh "CHỌN", cung cấp cho bạn dữ liệu từ bảng bạn đang chỉ định. Bạn đang nêu rõ ràng trong truy vấn của mình các giá trị cập nhật, do đó, bảng thứ hai không bị ảnh hưởng.


2

Bạn cũng có thể quan tâm đến việc sử dụng các phép nối trên các bản cập nhật, điều này cũng có thể.

Update someTable Set someValue = 4 From someTable s Inner Join anotherTable a on s.id = a.id Where a.id = 4
-- Only updates someValue in someTable who has a foreign key on anotherTable with a value of 4.

Chỉnh sửa: Nếu các giá trị bạn đang cập nhật không đến từ nơi nào khác trong cơ sở dữ liệu, bạn sẽ cần đưa ra nhiều truy vấn cập nhật.


1

Và bây giờ là cách dễ dàng

update speed m,
    (select 1 as id, 20 as speed union
     select 2 as id, 30 as speed union
     select 99 as id, 10 as speed
        ) t
set m.speed = t.speed where t.id=m.id

-1

sử dụng

REPLACE INTO`table` VALUES (`id`,`col1`,`col2`) VALUES
(1,6,1),(2,2,3),(3,9,5),(4,16,8);

Xin lưu ý:

  • id phải là khóa duy nhất chính
  • nếu bạn sử dụng khóa ngoại để tham chiếu bảng, REPLACE xóa rồi chèn, do đó, điều này có thể gây ra lỗi

-3

Sau đây sẽ cập nhật tất cả các hàng trong một bảng

Update Table Set
Column1 = 'New Value'

Hàng tiếp theo sẽ cập nhật tất cả các hàng trong đó giá trị của Cột2 lớn hơn 5

Update Table Set
Column1 = 'New Value'
Where
Column2 > 5

Có tất cả ví dụ của Unkwntech về việc cập nhật nhiều hơn một bảng

UPDATE table1, table2 SET
table1.col1 = 'value',
table2.col1 = 'value'
WHERE
table1.col3 = '567'
AND table2.col6='567'

-3

Có .. tôi có thể sử dụng INSERT ON DUPLICATE KEY UPDATE câu lệnh sql .. cú pháp: INSERT INTO tên_bảng (a, b, c) GIÁ TRỊ (a), b = GIÁ TRỊ (b), c = GIÁ TRỊ (c)


-5
UPDATE tableName SET col1='000' WHERE id='3' OR id='5'

Điều này sẽ đạt được những gì bạn đang tìm kiếm. Chỉ cần thêm id của. Tôi đã thử nó.


-7
UPDATE `your_table` SET 

`something` = IF(`id`="1","new_value1",`something`), `smth2` = IF(`id`="1", "nv1",`smth2`),
`something` = IF(`id`="2","new_value2",`something`), `smth2` = IF(`id`="2", "nv2",`smth2`),
`something` = IF(`id`="4","new_value3",`something`), `smth2` = IF(`id`="4", "nv3",`smth2`),
`something` = IF(`id`="6","new_value4",`something`), `smth2` = IF(`id`="6", "nv4",`smth2`),
`something` = IF(`id`="3","new_value5",`something`), `smth2` = IF(`id`="3", "nv5",`smth2`),
`something` = IF(`id`="5","new_value6",`something`), `smth2` = IF(`id`="5", "nv6",`smth2`) 

// Bạn chỉ cần xây dựng nó trong php như

$q = 'UPDATE `your_table` SET ';

foreach($data as $dat){

  $q .= '

       `something` = IF(`id`="'.$dat->id.'","'.$dat->value.'",`something`), 
       `smth2` = IF(`id`="'.$dat->id.'", "'.$dat->value2.'",`smth2`),';

}

$q = substr($q,0,-1);

Vì vậy, bạn có thể cập nhật bảng lỗ với một truy vấn


Tôi không downvote, nhưng tôi nghĩ rằng sự phản đối là để làm các thiết lập, khi nó không cần thiết (và bạn vẫn đang làm việc đó, khi bạn đang thiết somethingđể something)
v010dya
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.