2011-12-05 14 views
0

私の最初のplpgsqlコーディングの一部として、以下のコードを書きました。私の目には多くの繰り返しがあります。重複を取り除くにはどうすればよいですか?ストアドプロシージャの重複を減らすにはどうすればよいですか?

CREATE TABLE devices (
    device SERIAL PRIMARY KEY NOT NULL, 
    fingerprint VARCHAR UNIQUE NOT NULL 
); 

CREATE TABLE guests (
    guest SERIAL PRIMARY KEY NOT NULL, 
    uuid CHAR(36) NOT NULL 
); 

CREATE TABLE vms (
    vm SERIAL PRIMARY KEY NOT NULL, 
    guest SERIAL REFERENCES guests(guest), 
    device SERIAL REFERENCES devices(device), 
    name VARCHAR NOT NULL 
); 

CREATE OR REPLACE FUNCTION got_device_guest(fp TEXT, vmuuid CHAR(36), vmname TEXT) RETURNS VOID AS $BODY$ 
DECLARE 
    deviceid INT; 
    guestid INT; 
BEGIN 
    IF NOT EXISTS(SELECT * FROM devices WHERE devices.fingerprint = fp) THEN 
    INSERT INTO devices(fingerprint) VALUES (fp); 
    END IF; 
    SELECT device INTO deviceid FROM devices WHERE devices.fingerprint = fp; 
    IF NOT (EXISTS(SELECT * FROM guests WHERE guests.uuid = vmuuid)) THEN 
    INSERT INTO guests(uuid) VALUES (vmuuid); 
    END IF; 
    SELECT guest INTO guestid FROM guests WHERE guests.uuid = vmuuid; 
    IF NOT (EXISTS(SELECT * FROM vms WHERE vms.guest = guestid AND vms.device=deviceid)) THEN 
    INSERT INTO vms(guest, device, name) VALUES (guestid, deviceid, vmname); 
    END IF; 
END; 
$BODY$ LANGUAGE plpgsql; 
+0

推測私は重複が見えません。チェックされる各条件は、異なるビジネス検証を表します。各インサートは別々のテーブル用です。私が遠く離れて見えるのは、fpがヌル値のために評価されていないために挿入時にエラーが発生することだけです。とにかくそれは設計によるものです。 – xQbert

+0

これはプレーンSQL(IF ...の部分をWHERE節に移動することによって)に減らすことができますが、複雑さを軽減することはできません。ルールシステムを使用すると、3つのテーブルのビューのルールに縮小することもできますが、それは醜いハックになります(ルールは一般的ではありません) – wildplasser

答えて

2

ここでは繰り返しはありません。すべてのステートメントは異なるカラムなどの異なるテーブルにデータを挿入しています。共通のif not exists select ...(およびあなたのステートメントで類似しているもの)を共有する唯一の方法は、動的SQLを構築することです。

あなたがSQLインジェクション攻撃にさらされる可能性があり、あなたのprocの実行計画が再利用されないなどという理由は悪い考えです。これをそのまま残しておきます。