特定の条件を満たすレコードが満たされた場合にのみ、いくつかのデータをSQLテーブルに挿入するクエリセットを実行します。テーブルには4つのフィールドがあります:id
(プライマリ)、fund_id
、date
、price
クエリには3つのフィールドがあります:fund_id
、date
、price
。
したがって、私のクエリは次のようになります。
INSERT INTO funds (fund_id, date, price)
VALUES (23, '2013-02-12', 22.43)
WHERE NOT EXISTS (
SELECT *
FROM funds
WHERE fund_id = 23
AND date = '2013-02-12'
);
したがって、fund_id
とdate
に一致するレコードがまだ存在しない場合にのみ、データを挿入します。上記が正しい場合、毎回追加の選択ステートメントを実行する必要があるため、これを達成するための非常に非効率的な方法であると思います。
上記を達成するためのより良い方法はありますか?
編集:説明のため、fund_id
もdate
も一意のフィールドではありません。同じFund_idまたは日付を共有するレコードは存在しますが、別のレコードと同じfund_idと日付の両方を持つレコードはありません。
私が最初に選択されたとマークした答えは正しく、私が尋ねたものを達成しますが、これを行うためのより良い方法があります(他の人は認めましたが、入りませんでした)。複合一意インデックスは、fund_id
とdate
で構成されるテーブルに作成する必要があります。
ALTER TABLE funds ADD UNIQUE KEY `fund_date` (`fund_id`, `date`);
次に、レコードを挿入するときに、競合が発生したときに条件を追加します。
INSERT INTO funds (`fund_id`, `date`, `price`)
VALUES (23, DATE('2013-02-12'), 22.5)
ON DUPLICATE KEY UPDATE `price` = `price`; --this keeps the price what it was (no change to the table) or:
INSERT INTO funds (`fund_id`, `date`, `price`)
VALUES (23, DATE('2013-02-12'), 22.5)
ON DUPLICATE KEY UPDATE `price` = 22.5; --this updates the price to the new value
これにより、サブクエリのパフォーマンスが大幅に向上し、テーブルの構造が優れています。 MySQLによって値として扱われるため、一意のキー列にNULL値を含めることはできないという警告があります。
これは、これを達成するための簡単なソリューションかもしれません。
INSERT INTO funds (ID, date, price)
SELECT 23, DATE('2013-02-12'), 22.5
FROM dual
WHERE NOT EXISTS (SELECT 1
FROM funds
WHERE ID = 23
AND date = DATE('2013-02-12'));
p.s。あるいは(ID
が主キーの場合):
INSERT INTO funds (ID, date, price)
VALUES (23, DATE('2013-02-12'), 22.5)
ON DUPLICATE KEY UPDATE ID = 23; -- or whatever you need
this Fiddle を参照してください。
(一意の制約を作成するために)DDLを変更できないか、DMLの書き込みのみに制限され、テーブル全体に対する値のフィルタリング結果でnullをチェックすると仮定します。
insert into funds (ID, date, price)
select
T.*
from
(select 23 ID, '2013-02-12' date, 22.43 price) T
left join
funds on funds.ID = T.ID and funds.date = T.date
where
funds.ID is null