我使用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。我编写的代码如下所示:
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 INTO public."Student"(
        student_id, "firstName", "lastName", location, age)
        VALUES (2231, 'A', 'Van Nguyen', 'DN',26);

它不起作用。PostgresSQL引发我异常:
查询:从学生中选择地点location=NEW.location
CONTEXT:PL/pgSQL函数student_no()第8行,位于SQL语句SQL
状态:42P01。
我有个问题:
如何从输入用户获取数据并与来自
数据库。如果不一样,执行命令随机。同样的价值来自
数据库,它必须返回并创建新的随机。请帮助我
因为我只工作一天,不处理问题。

最佳答案

有不止一个问题
SELECT location FROM Student WHERE location = NEW.location;-PLpgSQL不允许在没有结果目标的情况下执行查询。ForSELECTaINTO子句是必需的。如果不需要存储结果,请使用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这样的查询都不能很好地防止重复行。如果没有更积极的触发器锁定,就不可能做好这项工作。你的例子很好地说明了如何不使用触发器。在显式调用的函数(例如plpgsql)中使用此逻辑,但在触发器中不使用。对这种情况来说,这是个糟糕的地方。
PLpgSQL是不区分大小写的语言-不要使用驼峰符号。SQL是不区分大小写的语言-不要使用驼峰符号,也不要使用像“lastName”这样区分大小写的SQL标识符-这是去精神病院最短的路。

关于sql - 随机执行plpgsql时,如何将用户输入的值与数据库中的数据进行比较,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55431005/

10-12 14:16
查看更多