7

私は2つのテーブルを持っています:

 CREATE TABLE "user"
    (
      username character varying(35) NOT NULL,
      CONSTRAINT user_pk PRIMARY KEY (username)
    )
    CREATE TABLE item
    (
      id serial NOT NULL,
      username character varying(35),
      user_item_number integer,
      item_value character varying(35),
      CONSTRAINT item_pk PRIMARY KEY (id),
      CONSTRAINT item_fk FOREIGN KEY (username)
          REFERENCES "user" (username) MATCH SIMPLE
          ON UPDATE NO ACTION ON DELETE NO ACTION,
      CONSTRAINT unique_item_username UNIQUE (username, user_item_number)
    )

ここに画像の説明を入力

user_item_numberごとに個別に自動インクリメントしたいと思いますusername。次の画像は例を示しています。For each username: ( user1, user2)user_item_numberは 1 から始まり、1 ずつ増加します。 ここに画像の説明を入力

user_item_number挿入する前に、挿入される最大値を取得usernameしてインクリメントするトリガーを使用する必要があると思います。しかし、そのトリガーの書き方がわかりません。

また、同時アクセスを考慮する方法もわかりません(同時アクセスは、同じ値の複数の行を挿入しますusername)。username同じ 2 つの行が挿入されたときに制約違反エラーが発生したくありません。user_item_numberそのトリガーでそのエラーをキャッチし、もう一度 user_item_number値をインクリメントしたいと思います。

何か案が?

4

3 に答える 3

1

Auto inc は一意である必要があり、テーブルごとに 1 つだけです。

だからあなたが望むと思われるものに基づいて

User(User_ID PK, ...)
UserItem(User_Item_ID PK, User_ID FK, ...)
UserItemValue(User_Item_Value_ID PK, User_Item_ID FK, ...)

正規化の観点から向かうべき場所です

于 2013-08-06T12:26:02.527 に答える
0

解決策を見つけました。トリガーとプロシージャを書きました:

create OR REPLACE function myinsert() RETURNS trigger as $$
    BEGIN
        if NEW.user_item_number is not null then return NEW;
        end if;
        loop
            <<roolbac_to>>
            declare
                max INTEGER:=null;
            begin
            SELECT count(user_item_number) into max from item where username=NEW.username;
            if max is null then
                max:=1;
            ELSE
                max=max+1;
            end if;
            INSERT INTO item( username, user_item_number, item_value) VALUES (NEW.username,max, NEW.item_value);
            exit;
            exception WHEN unique_violation THEN
            --do nothing
            end;
        end loop;
    return null;
    end;

$$ LANGUAGE 'plpgsql';

CREATE TRIGGER trig1
 before insert 
    ON item
   FOR EACH ROW
EXECUTE PROCEDURE myinsert();

このソリューションはギャップの作成を可能にしますが、私にとっては問題ありません。

インサートの代わりにトリガーをモークしたかったのですが、それは不可能です。そこで、トリガーを挿入してnullを返す前に作成しました。Insert はプロシージャ内で実行されます。命令:

if NEW.user_item_number is not null then return NEW;
    end if;

再発を許さないことです

于 2013-08-07T11:28:20.563 に答える