我使用Postgres数据库,每当用户将任何记录插入数据库时,我想生成随机student_no。命令如下:
NEW.booking_no: = array_to_string (ARRAY (SELECT chr ((48 + round (random () * 9)) :: integer) FROM generate_series (1,10)), '');
我的表结构如下:
Name Table : Student
(id Pk,
firstName varchar,
lastName varchar,
student_no varchar,
location varchar,
age integer
)
为方便起见,我用plpgsql实现了编写函数和触发器,如下所示:
//Create function
CREATE OR REPLACE FUNCTION student_no()
RETURNS TRIGGER AS
$$
BEGIN
NEW.student_no := array_to_string(ARRAY(SELECT chr((48 + round(random() * 9)) :: integer) FROM generate_series(1,10)), '');
RETURN NEW;
END
$$ LANGUAGE plpgsql;
//create trigger
CREATE TRIGGER student_no
BEFORE INSERT
ON public."Student"
FOR EACH ROW
EXECUTE PROCEDURE student_no();
//Data User Insert to database
INSERT INTO public."Student"(
student_id, "firstName", "lastName", location, age)
VALUES (2231, 'Join', 'David', 'UK',26);
当我插入时,它成功创建并在我的数据库中随机student_no。太棒了但我想比较学生相同的位置,student_no它不能重复,如果不同它可以复制。如果相同的位置和函数随机相同student_no,则必须创建另一个随机student_no。我写代码看起来像:
CREATE OR REPLACE FUNCTION student_no()
RETURNS TRIGGER AS
$$
DECLARE
canIUseIt boolean := false;
randomNumber BIGINT;
BEGIN
//loop when random success
WHILE ( not ( canIUseIt ) ) LOOP
randomNumber := array_to_string(ARRAY(SELECT chr((48 + round(random() * 9)) :: integer) FROM generate_series(1,10)), '');
//Get data from user input and compare with database. I not sure it true. If it wrong, please help me fix it.
//New.location : data from user insert. I think
// location data from database
SELECT location FROM Student WHERE location = NEW.location;
IF NOT FOUND THEN
canIUseIt = true;
END IF;
END LOOP;
$$ LANGUAGE plpgsql;
//If not duplicate, insert random number to database. And break loop.
IF ( canIUseIt ) THEN
RETURN NEW.booking_no: = array_to_string (ARRAY (SELECT chr ((48 + round (random () * 9)) :: integer) FROM generate_series (1,10)), '');
END IF;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER student_no
BEFORE INSERT
ON public."Student"
FOR EACH ROW
EXECUTE PROCEDURE student_no();
但是当我执行命令Insert时
INSERT INTO public."Student"(
student_id, "firstName", "lastName", location, age)
VALUES (2231, 'A', 'Van Nguyen', 'DN',26);
它不起作用。 PostgresQL抛出异常:
QUERY:SELECT FROM FROM Student WHERE location = NEW.location语境:PL / pgSQL函数student_no()第8行,SQL语句SQL状态:42P01。
我有个问题 :
有一个以上的问题
SELECT location FROM Student WHERE location = NEW.location;
- PLpgSQL不允许在没有结果目标的情况下执行查询。对于SELECT
,需要INTO
条款。如果你不需要存储结果,使用PERFORM
语句或更好(在这种情况下),使用谓词EXISTS
代替:
-- bad
SELECT location FROM student WHERE location = NEW.location;
IF NOT FOUND THEN
can_i_use_it := true;
END IF;
-- can works
PERFORM location FROM student WHERE location = NEW.location;
IF NOT FOUND THEN
can_i_use_it := true;
END IF;
-- better
IF NOT EXISTS(SELECT * FROM student WHERE ...) THEN
can_i_use_it := true;
END IF;
-- good
can_i_use_it := EXISTS(SELECT * FROM Student WHERE location = NEW.location)
UNIQUE
索引,像IF EXISTS(some query) THEN
这样的查询不能很好地防止重复行。没有更积极的锁定触发器就不可能做得好。您的示例是如何不使用触发器的好示例。在显式调用的函数中使用此逻辑(例如在plpgsql中),但不在触发器中。对于这种情况,它是不好的地方。