1

私は次の機能を持っています:

CREATE FUNCTION user_delete(IN id INT4)
  RETURNS VOID
AS
  $BODY$
  BEGIN
    SELECT * FROM "user" WHERE user_id = id FOR UPDATE;
    DELETE FROM user_role WHERE user_id = id;
    DELETE FROM user_permission WHERE user_id = id;
    DELETE FROM permission_cache WHERE user_id = id;
    DELETE FROM access WHERE user_id = id;
    DELETE FROM "user" WHERE user_id = id;
  END;
  $BODY$
LANGUAGE plpgsql VOLATILE;

これをPHP PDOで使用します:

$stmt = $pdo->prepare('SELECT * FROM user_delete(?)');
$stmt->execute(array($user['id']));

結果には今が含まれています

array(
    array('user_delete' => '')
)

そして、

$stmt->rowCount();

は常に 1 つです。

これを修正することは可能ですか: 関数によって何も返されず (無効であるため)、rowCount によって影響を受ける行の数が返されますか?

解決:

php:

public function delete($id)
{
    try {
        $this->__call('user_delete', array($id));
    } catch (\PDOException $e) {
        if ($e->getCode() === 'UE404')
            throw new NotFoundException();
        else
            throw $e;
    }
}

SQL:

CREATE FUNCTION user_delete(IN id INT4)
  RETURNS VOID
AS
  $BODY$
  BEGIN
    DELETE FROM user_role WHERE user_id = id;
    DELETE FROM user_permission WHERE user_id = id;
    DELETE FROM permission_cache WHERE user_id = id;
    DELETE FROM access WHERE user_id = id;
    DELETE FROM "user" WHERE user_id = id;
    IF NOT FOUND THEN
      RAISE SQLSTATE 'UE404' USING MESSAGE = 'not found for delete';
    END IF;
  END;
  $BODY$
LANGUAGE plpgsql VOLATILE;

戻り値の型で長さゼロの結果を返すことができますが、リソースが見つからないときsetof voidに強制的にスローする場合は必要ありません...PDOException

4

1 に答える 1

3

以下を使用できます。

GET DIAGNOSTICS integer_var = ROW_COUNT;

.. 関数がカウントを返すようにします。詳細はマニュアルにて。

例:

CREATE OR REPLACE FUNCTION user_delete(id int, OUT del_ct int) AS
$func$
DECLARE
   i int;  -- helper var
BEGIN
   DELETE FROM user_role WHERE user_id = $1;
   GET DIAGNOSTICS del_ct = ROW_COUNT;  -- init

   DELETE FROM user_permission WHERE user_id = $1;
   GET DIAGNOSTICS i = ROW_COUNT;  del_ct := del_ct + i;

   DELETE FROM permission_cache WHERE user_id = $1;
   GET DIAGNOSTICS i = ROW_COUNT;  del_ct := del_ct + i;

   DELETE FROM access WHERE user_id = $1;
   GET DIAGNOSTICS i = ROW_COUNT;  del_ct := del_ct + i;

   DELETE FROM "user" WHERE user_id = $1;
   GET DIAGNOSTICS i = ROW_COUNT;  del_ct := del_ct + i;
END
$func$  LANGUAGE plpgsql;

あなたはこれを最初のステートメントとして持っていました:

SELECT * FROM "user" WHERE user_id = $1 FOR UPDATE;

無効な構文 -ターゲットのないステートメントに使用PERFORMする必要がある plpgsql 関数内:SELECT

PERFORM * FROM "user" WHERE user_id = $1 FOR UPDATE;

ただし、次のDELETEステートメントも同様に行をロックします。そもそも手動でロックするFOR UPDATE必要はありません。

追加された は、任意の変数のように割り当てることができるパラメーターをOUT del_ct int宣言し、関数の最後に自動的に返されます。OUTまた、明示的なRETURNS宣言が不要になります。

于 2013-08-12T18:37:58.750 に答える