문제
나는 알고 삽입할 수 있는 여러 행에는 일단 방법이 있을 업데이트를 여러 행에 한 번(에서와 같이,하나의 쿼리로)에서 MySQL?
편집:예를 들어 내가 다음
Name id Col1 Col2
Row1 1 6 1
Row2 2 2 3
Row3 3 9 5
Row4 4 16 8
내가 결합하려는 다음과 같은 모든 업데이트로 한 쿼리
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;
해결책
예,그 가능-사용할 수 있습 INSERT...에 복제 키 업데이트합니다.
를 사용하여 예를 들어:
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);
다른 팁
했기 때문에 동적인 값을 사용할 필요가 있는 경우 또는 사례에 대한 열 업데이트 할 수 있습니다.그것이해져 가고 못생긴 하지만 작업해야 합니다.
를 사용하여를 들어,당신은 그것을 할 수 있습 다음과 같:
UPDATE table SET Col1 = CASE id WHEN 1 THEN 1 WHEN 2 THEN 2 WHEN 4 THEN 10 ELSE Col1 END, Col2 = CASE id WHEN 3 THEN 3 WHEN 4 THEN 12 ELSE Col2 END WHERE id IN (1, 2, 3, 4);
문제는 오직 나를 확장하는 주제와는 다른 대답이다.
내 포인트는 가장 쉬운 방법은 그것을 달성하기 위해 단지를 랩으로 여러 쿼리를 수 있습니다.허용된 응답 INSERT ... ON DUPLICATE KEY UPDATE
좋은 해킹,그러나 알고 있어야 하는 단점과 제한사항:
- 되는 것으로 말하면 일을 시작하는 쿼리와 행의 기본 키가 존재하지 않에 테이블을 쿼리를 삽입하는 새로운"half-baked"기록합니다.아마도 그것은 당신이 무엇을 원
- 테이블이 있는 경우으로 null 이 아닌 필드없이 기본값이고 싶지 않아요 이 분야에서 쿼리,당신을 얻을 것
"Field 'fieldname' doesn't have a default value"
MySQL 경고를 하지 않는 경우에 삽입하는 단 하나 줄에 모두.그것이 문제가 당신을 얻을,당신이 할 것을 결정하는 경우 엄격하고 돌 mysql 경고로 런타임 예외에서의 응용이다.
제가 몇 가지 성능 테스트의 세 가지 제안된 변형을 포함 INSERT ... ON DUPLICATE KEY UPDATE
변형,변형으로"케이스//때 그런 다음"절하고 순진한 방법으로 트랜잭션이 있습니다.당신이 얻을 수 있습니다 python 코드 및 결과 기.전반적인 결론은 변형 케이스에 문의 것으로 밝혀졌으로 두 배 빠른 속도로 다른 두 개 있지만,그것은 매우 열심히 쓰는 정확하고 사출 안전한 코드에 대한 그것은,그래서 개인적으로 스틱을하는 가장 간단한 방법:를 사용하여 트랜잭션이 있습니다.
편집: 연구 결과의 Dakusan 나 성능을 추정하지 않은 매우 유효합니다.참조하십시오 이 답변 다른,더 정교한 연구이다.
이는 또 다른 유용한 옵션은 아직 언급하지 않:
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;
다음과 같은 모든 적용 InnoDB.
나고의 이동 속도를 3 가지 방법이 중요합니다.
3methods:
- 하려면:면에 복제 키 업데이트
- 트랜잭션:어디에 당신 업데이트 각 레코드에 대한 트랜잭션 내에서
- 경우:는 경우/경우 각각 다른 기록 내에서 업데이트
나는 그냥 시험이,그리고 삽입하는 방법 6.7x 보다 나를 더 빨리 거래 방법입니다.를 즐길 수 있는 빠르고 편리한 방법을 설정 모두 3,000 30,000 행이 있습니다.
거래 방법은 여전히 실행하는 각 개별적으로 쿼리 시간이 걸리지만,일괄 처리 결과를 메모리에,또는 동안 실행됩니다.거래 방법은 또한 꽤 비싼 모두에 복제 및 쿼리를 기록합니다.
심지어 경우 방법 ×41.1 보다 느리게 삽입하는 방법 w/30,000 레코드(6.1x 보다 느린 트랜잭션).고 75x 느린에 MyISAM.삽입 및 케이스 방법도에서~1,000 기록합니다.에서도 100 레코드 케이스는 방법이 간신히 빠르다.
그래서 일반적으로,나는 느낌을 삽입하는 방법은 모두 최고 쉬운 사용합니다.쿼리를 작고 쉽게 읽기만을 1 쿼리의 작업입니다.이 모두 적용됩니다 InnoDB 및 MyISAM.
보너스 재료:
에 대한 솔루션을 삽입하는 기본값이 아닌 필드를 일시적으로 끄는 관련 SQL 모드: SET SESSION sql_mode=REPLACE(REPLACE(@@SESSION.sql_mode,"STRICT_TRANS_TABLES",""),"STRICT_ALL_TABLES","")
.는지 확인을 저장할 sql_mode
먼저 계획인 경우에으로 복귀습니다.
에 대한 의견을 나는 본 적이 말하는 다음의 특징을 간를 사용하여 삽입하는 방법으로,나이는 너무 그리고 그것은 보인다되지 않습니다.
코드를 실행하는 테스트는 다음과 같습니다.그것은 또한 출력이 있습니다.SQL 파일을 제거하 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).';');
}
UPDATE table1, table2 SET table1.col1='value', table2.col1='value' WHERE table1.col3='567' AND table2.col6='567'
이 일을 생각합니다.
거기에 참조 MySQL 설명서 여러 테이블이 있습니다.
사용 임시 테이블
// 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`");
}
할 수 있는 별명 같은 테이블을 당신에게 id 를 삽입할여(하는 경우의 행 업데이트:
UPDATE table1 tab1, table1 tab2 -- alias references the same table
SET
col1 = 1
,col2 = 2
. . .
WHERE
tab1.id = tab2.id;
또한,그것은 보이는 것이 분명할 수도 있습니다 업데이트를 다른 테이블에서뿐만 아니라.이 경우,업데이트로 선택""문을 제공,당신은 테이블에서 데이터를 지정됩니다.당신이 명시적으로 쿼리에서 업데이트 값 그래서 두 테이블은 영향을 받지 않습니다.
왜 아무도 언급 여러 문에서 하나 쿼리?
Php 에서 사용 multi_query
방법 mysqli 인스턴스입니다.
서 php 설명서
MySQL 선택적으로 허용하는 데는 여러 문이 하나의 문에서 문자열입니다.보내는 여러 문을 한 번에 감소하는 클라이언트-서버 라운드 여행은 그러나 필요한 특별한 처리가 있습니다.
결과는 다음과 같습니다 비교하는 다른 3 가지 방법을 업데이트 30,000 원.코드 찾을 수 있습니다 기 을 기반으로 응답에서@Dakusan
트랜잭션:5.5194580554962
하려면:0.20669293403625
경우:16.474853992462
Multi:0.0412278175354
당신이 볼 수 있듯이,여러 문 쿼리를 보다 더 효율적인 최고 대답합니다.
만약 당신이이 같은 오류 메시지:
PHP Warning: Error while sending SET_OPTION packet
필요할 수 있는 증가 max_allowed_packet
mysql config 파일에서 내 컴퓨터 /etc/mysql/my.cnf
고 다시 시작 mysqld.
당신은 또한에 관심이있을 수 있습니다 사용하여 결합에 업데이트뿐만 아니라 수 있습니다.
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.
편집:는 경우 값을 업데이트하지 않은 오는 다른 곳에서 데이터베이스에서,당신을 발행 할 필요가 여러 업데이트 검색어입니다.
가 설정을 변경할 수 있습니다'라는 문 멀티'를 비활성화 MySQL 의'안전 메커니즘'되는 것을 방지(하나 이상)주입 명령입니다.일반적인 MySQL 의'빛나는'구현에,그것은 또한 사용자를 방지 하기에서 효율적인 쿼리를 처리합니다.
여기에서(http://dev.mysql.com/doc/refman/5.1/en/mysql-set-server-option.html 는)일부에 대한 정보 C 의 구현을 설정합니다.
를 사용하는 경우 PHP 사용할 수 있습니다 mysqli 을 다 계산서(내가 생각하 php 와 함께 제공되었 mysqli 한)
$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();
는 희망 도움이 됩니다.
사
REPLACE INTO`table` VALUES (`id`,`col1`,`col2`) VALUES
(1,6,1),(2,2,3),(3,9,5),(4,16,8);
참고:
- id 는 주요한 독특한 열쇠
- 당신이 사용하는 경우 외국 열쇠 표를 참조,교체 삭제 삽입한 후,그래서 이것도 오류가 발생
다음 업데이트됩니다 모든 행에서 한 테이블
Update Table Set
Column1 = 'New Value'
다음 중 하나이 업데이트됩니다 모든 행의 값 Column2 보다 더 5
Update Table Set
Column1 = 'New Value'
Where
Column2 > 5
가 Unkwntech's 를 들어의 업데이트 하나 이상의 테이블
UPDATE table1, table2 SET
table1.col1 = 'value',
table2.col1 = 'value'
WHERE
table1.col3 = '567'
AND table2.col6='567'
그리고 그것은 사용하여 가능한 삽입에 복제 키 업데이트 sql 문..syntax:에 삽입 table_name(a,b,c)값(1,2,3),(4,5,6) 에 복제 키 업데이트=값(a),b=값(b),c=값(c)
PHP 내가 이것을 했다.사용 세미콜론으로 분할 배열한 후 제출을 통해 루프입니다.
$con = new mysqli('localhost','user1','password','my_database');
$batchUpdate = true; /*You can choose between batch and single query */
$queryIn_arr = explode(";", $queryIn);
if($batchUpdate) /* My SQL prevents multiple insert*/
{
foreach($queryIn_arr as $qr)
{
if(strlen($qr)>3)
{
//echo '<br>Sending data to SQL1:<br>'.$qr.'</br>';
$result = $conn->query($qr);
}
}
}
else
{
$result = $conn->query($queryIn);
}
$con->close();
UPDATE tableName SET col1='000' WHERE id='3' OR id='5'
이해 당신은'r 찾고 있습니다.다만 더 추가한다.나는 그것을 테스트했습니다.
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`)
//당신은 단지 그것을 건물에서 다음과 같 php
$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);
업데이트할 수 있도록 구멍이 하나인 테이블을 쿼리