SQL Update 문을 실행하기 전에 테스트하는 방법은 무엇입니까?


96

경우에 따라 프로덕션에서 UPDATE 문을 실행하면 하루를 절약 할 수 있습니다. 그러나 지루한 업데이트는 초기 문제보다 더 나쁠 수 있습니다.

테스트 데이터베이스를 사용하지 않는 한 업데이트 문을 실행하기 전에 수행 할 작업을 알려주는 옵션은 무엇입니까?

답변:


53

Imad가 말한대로 트랜잭션을 사용하는 것 외에도 (어쨌든 필수 사항이어야 함) UPDATE와 동일한 WHERE 절을 사용하여 select를 실행하여 영향을받는 행을 온 전성 검사 할 수도 있습니다.

따라서 UPDATE가

UPDATE foo
  SET bar = 42
WHERE col1 = 1
  AND col2 = 'foobar';

다음은 업데이트 될 행을 보여줍니다.

SELECT *
FROM foo
WHERE col1 = 1
  AND col2 = 'foobar';

1
데이터를 확인하려면 트랜잭션을 사용하는 것이 좋습니다. 그가 결과를 확인하고 싶다고 가정하면 그의 진술이 'SET bar = 42'보다 더 복잡하다고 결론을 내립니다. 그래서 그의 세션 내에서 그는 결과 데이터 세트를 테스트하기 위해 여러 쿼리를 만들 수있을 것입니다 ...
Imad Moqaddem

3
@ImadMoqaddem : 나는 동의하고 내가 "쓴 이유의 이마 드 말했듯이 트랜잭션을 사용하는 외에 "
a_horse_with_no_name

그리고 FOREIGN KEY UPDATE CASCADESQL이 실패하면
Green

@Green : "실패"란 무엇을 의미합니까?
a_horse_with_no_name

75

거래는 어떻습니까? 롤백 기능이 있습니다.

@see https://dev.mysql.com/doc/refman/5.0/en/commit.html

예를 들면 :

START TRANSACTION;
SELECT * FROM nicetable WHERE somthing=1;
UPDATE nicetable SET nicefield='VALUE' WHERE somthing=1;
SELECT * FROM nicetable WHERE somthing=1; #check

COMMIT;
# or if you want to reset changes 
ROLLBACK;

SELECT * FROM nicetable WHERE somthing=1; #should be the old value

아래 @rickozoe의 질문에 대한 답변 :

일반적으로이 행은 한 번 실행되지 않습니다. PHP fe에서는 다음과 같이 작성합니다 (아마도 조금 더 깔끔하지만 빠르게 대답하고 싶었습니다 ;-)).

$MysqlConnection->query('START TRANSACTION;');
$erg = $MysqlConnection->query('UPDATE MyGuests SET lastname='Doe' WHERE id=2;');
if($erg)
    $MysqlConnection->query('COMMIT;');
else
    $MysqlConnection->query('ROLLBACK;');

또 다른 방법은 MySQL 변수를 사용하는 것입니다 ( https://dev.mysql.com/doc/refman/5.7/en/user-variables.htm l 및 https://stackoverflow.com/a/18499823/1416909 참조 ) :

# do some stuff that should be conditionally rollbacked later on

SET @v1 := UPDATE MyGuests SET lastname='Doe' WHERE id=2;
IF(v1 < 1) THEN
    ROLLBACK;
ELSE
    COMMIT;
END IF;

하지만 좋아하는 프로그래밍 언어로 제공되는 언어 래퍼를 사용하는 것이 좋습니다.


1
중첩 된 트랜잭션에서 예기치 않은 결과가 발생합니다.
스콘

예를 들어 주시겠습니까?
Marcel Lange

@JCM 및 기타, 업데이트 문이 3 행에서 성공했는지 어떻게 알 수 있으므로 커밋하고 롤백 할 수 있습니까?
ricko zoe 2017

57

자동 커밋 끄기 ...

MySQL

set autocommit=0;

현재 세션에 대해 autommit을 해제합니다.

문을 실행하고 변경 사항을 확인한 다음 잘못된 경우 롤백하거나 예상 한대로 커밋합니다!

편집 : 선택 쿼리를 실행하는 대신 트랜잭션을 사용하는 이점은 결과 집합을 더 쉽게 확인할 수 있다는 것입니다.


4
@dystroy : 모든 현명한 DBMS는 트랜잭션을 지원합니다.
a_horse_with_no_name

7
트랜잭션을 빠르게 커밋하거나 롤백하십시오. 그렇지 않으면 다른 트랜잭션을 차단할 위험이 있습니다. 최악의 경우 애플리케이션이 중단 될 수 있습니다. 쿼리를 실행 한 다음 점심을 먹고 결과를 확인하는 것은 좋지 않습니다. :-)
Gary McGill

@GaryMcGill : 보류중인 트랜잭션은 (적어도 최신 DBMS에서는) 다른 쓰기 트랜잭션 만 차단 합니다.
a_horse_with_no_name

5
@dystroy : 불행히도 MyISAM은 모든 곳에서 사용되고 있으며 저는 DBA가 아닙니다.
static_rtti 2012-06-13

1
SQL 문 추가 :)
Imad Moqaddem

11

나는 이것이 다른 답변의 반복이라는 것을 알고 있지만 업데이트 테스트를 위해 추가 단계를 수행하기 위해 감정적 인 지원이 있습니다 : D

업데이트 테스트를 위해 해시 #은 친구입니다.

다음과 같은 업데이트 문이있는 경우 :

UPDATE 
wp_history
SET history_by="admin"
WHERE
history_ip LIKE '123%'

테스트를 위해 UPDATE 및 SET를 해시 한 다음 다시 해시합니다.

SELECT * FROM
#UPDATE
wp_history
#SET history_by="admin"
WHERE
history_ip LIKE '123%'

간단한 문장에서 작동합니다.

실질적으로 필수적인 추가 솔루션은 프로덕션 테이블에서 업데이트를 사용할 때마다 복사본 (백업 중복)을 얻는 것입니다. Phpmyadmin> 작업> 복사 : table_yearmonthday. 테이블이 100M 미만인 경우 몇 초 밖에 걸리지 않습니다.


5

직접적인 대답은 아니지만 , WHERE절을 먼저 입력하여 피할 수있는 지루한 데이터 상황을 많이 보았습니다 ! 때때로 a WHERE 1 = 0는 작업 진술을 안전하게 작성하는 데 도움이 될 수 있습니다. 영향을받는 행을 추정하는 예상 실행 계획을 살펴 보는 것도 유용 할 수 있습니다. 그 외에도 다른 사람들이 말한 것처럼 롤백하는 트랜잭션에서.


2
@SystemParadox-아무것도 아니지만 WHERE 1 = 0다른 DBMS로 작업하는 사람이 있으면 더 이식성이 좋습니다. 예를 들어 SQL Server는 WHERE FALSE.
David M

2

테스트하려는 이러한 경우에는 현재 열 값과 곧 업데이트 될 열 값 에만 집중하는 것이 좋습니다 .

WHMCS 가격을 업데이트하기 위해 작성한 다음 코드를 살펴보십시오.

# UPDATE tblinvoiceitems AS ii

SELECT                        ###  JUST
    ii.amount AS old_value,   ###  FOR
    h.amount AS new_value     ###  TESTING
FROM tblinvoiceitems AS ii    ###  PURPOSES.

JOIN tblhosting AS h ON ii.relid = h.id
JOIN tblinvoices AS i ON ii.invoiceid = i.id

WHERE ii.amount <> h.amount   ### Show only updatable rows

# SET ii.amount = h.amount

이런 식으로 기존 값과 새 값을 명확하게 비교합니다.


1

where업데이트 쿼리에서 적용 하는 모든 조건 으로 동일한 테이블에서 선택 쿼리를 실행 합니다.


0

SELECT그것을 만들어라.

당신이 얻은 것처럼

UPDATE users SET id=0 WHERE name='jan'

그것을 변환

SELECT * FROM users WHERE name='jan'


0

한 가지 더 옵션은 MySQL에 쿼리 계획을 요청하는 것입니다. 이것은 두 가지를 알려줍니다.

  • 쿼리에 구문 오류가 있는지 여부, 그렇다면 쿼리 계획 명령 자체가 실패합니다.
  • MySQL이 쿼리 실행을 계획하는 방법 (예 : 사용할 인덱스)

MySQL 및 대부분의 SQL 데이터베이스에서 query plan 명령은 describe이므로 다음을 수행합니다.

describe update ...;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.