SQL Updateステートメントを実行する前にテストする方法は?


96

場合によっては、本番環境でUPDATEステートメントを実行すると、その日を節約できます。ただし、更新の中断は、最初の問題よりも悪化する可能性があります。

テストデータベースを使用する前に、更新ステートメントを実行する前に何を実行するかを指示するオプションは何ですか?

回答:


51

Imadが言ったようにトランザクションを使用することに加えて(とにかく必須である必要があります)、UPDATEと同じWHERE句を使用して選択を実行することによって影響を受ける行を確認することもできます。

だからあなたが更新した場合

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:同意するので、Imadが言ったようにトランザクションを使用することを除いて」書いたのはそのためです
a_horse_with_no_name

そして、FOREIGN KEY UPDATE CASCADEあなたのSQLが失敗した場合
グリーン

@グリーン:「失敗」とはどういう意味ですか?
a_horse_with_no_name 2017年

73

トランザクションについてはどうですか?彼らはロールバック機能を備えています。

@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 2016

@JCMと他のユーザーは、3行目でupdateステートメントが成功したかどうかを確認して、コミットしてロールバックできるようにするにはどうすればよいですか?
ricko zoe

56

自動コミットオフ...

MySQL

set autocommit=0;

現在のセッションのautommitをオフに設定します。

ステートメントを実行し、何が変更されたかを確認し、それが間違っている場合はロールバックするか、期待どおりの場合はコミットします。

編集:選択クエリを実行する代わりにトランザクションを使用する利点は、結果セットを簡単に確認できることです。


4
@dystroy:すべての賢明なDBMSがトランザクションをサポートします。
a_horse_with_no_name

7
トランザクションをすばやくコミットまたはロールバックすることを忘れないでください。そうしないと、他のトランザクションをブロックしてしまうリスクがあり、最悪の場合、アプリケーションが停止してしまいます。クエリを実行して昼食をとり、結果を確認するのは良い考えではありません。:-)
Gary McGill

@GaryMcGill:保留中のトランザクションは(少なくとも最新のDBMSでは)他の書き込みトランザクションのみをブロックします。
a_horse_with_no_name 2012年

5
@dystroy:残念ながら、MyISAMはどこでも使用されており、私はDBAではありません。
static_rtti

1
SQLステートメントが追加されました:)
Imad Moqaddem 2014年

11

私はこれが他の答えの繰り返しであることを知っていますが、アップデートをテストするための追加のステップを実行するためのいくつかの感情的なサポートがあります

更新のテストでは、ハッシュ#があなたの友達です。

次のような更新ステートメントがある場合:

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

あなたはUPDATEをハッシュしてテストのために設定し、次にそれらをハッシュして戻します:

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

単純なステートメントで機能します。

さらに実用的な必須のソリューションは、プロダクションテーブルで更新を使用する場合は常に、コピー(バックアップ複製)を取得することです。Phpmyadmin>操作>コピー:table_yearmonthday。100M以下のテーブルの場合、数秒かかります。


5

直接的な答えではありませんが、最初に句を入力することでWHERE回避できたはずのプロダクションデータの状況が数多く見られました。ときどき、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'

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.