ユーザーによる「アイテム」の使用をカウントするために使用されるPostgreSQL関数があります。カウンター値はテーブルに保存されます:
ユーザー_アイテム
user_id - integer (fk)
item_id - integer (fk)
counter - integer
最大あります。アイテムごとにユーザーごとに 1 つのカウンター (一意のキー)。
これが私の機能です:
CREATE OR REPLACE FUNCTION increment_favorite_user_item (item integer, userid integer) RETURNS integer AS
$BODY$
DECLARE
new_count integer; -- Usage counter
BEGIN
IF NOT EXISTS(SELECT 1 FROM users_items WHERE user_id = userid AND item_id = itemid)
THEN
INSERT INTO users_items ("user_id", "item_id", "counter") VALUES (userid, itemid, 1); -- First usage - create new counter
new_amount = 1;
ELSE
UPDATE users_items SET count = count + 1 WHERE (user_id = userid AND item_id = itemid); -- Increment counter
SELECT counter INTO new_count FROM users_items WHERE (user_id = userid AND item_id = itemid);
END IF;
RETURN new_count;
END;
$BODY$
LANGUAGE 'plpgsql'
VOLATILE;
これはアプリケーションによって使用され、複数回呼び出すことができます。アイテムが特定のユーザーにとって新しい場合 (users_items テーブルのレコードが存在しない場合)、同じユーザーとアイテムに対して関数を次々に呼び出すまで、すべてが正常に機能します。
2 回目の関数呼び出しで、「キー (user_id, item_id)=(1, 7912) は既に存在します」という固有の違反が発生します。「存在しない場合」チェックが正しく機能しないようです.2番目の関数呼び出しは最初の関数呼び出しによって挿入されたレコードを認識せず、同じ行を挿入しようとするため、uq チェックが失敗します。
問題を解決するにはどうすればよいですか?
すべての関数呼び出しは、別のトランザクションで実行されます。