0

我有一个具有以下数据模型的 PostGreSQL 数据库:

CREATE TABLE staff (s_id serial UNIQUE, name, username, password, email)
CREATE TABLE institution (i_id serial UNIQUE, name);
CREATE TABLE isStaffOf (i_id, s_id); //foreign key references

当用户提交表单时,我有一个 PHP 脚本,它将信息写入前两个数据表并自动生成 s_id 和 i_id 值。伟大的!

我已经尝试了一些 PHP 修改,以使系统将 s_id 和 i_id 写入 isStaffOf 关系,以便它可以强制执行我的项目所需的显式 1..1 关系,但在提交时它说我的数据类型不足。请参阅下面的 PHP 代码。

    $name = $_POST["name"];
    $username = $_POST["username"];
    $password = $_POST["password"];
    $email = $_POST["email"];
    $institution = $_POST["institution"];

    $conn = pg_connect("host=***** port=**** dbname=****** user=**** password=******");
    $staffWrite = pg_query("INSERT INTO staff(name, username, password, email) VALUES ('$name', '$username', '$password', '$email')");
    $instiWrite = pg_query("INSERT INTO institution(name) VALUES ('$institution')");

    $instiFK=pg_query("SELECT i_id FROM institution WHERE name='$institution'");
    $staffFK=pg_query("SELECT s_id FROM staff WHERE name='$username'");

    $sql=("INSERT INTO isstaffof(i_id, s_id) VALUES ('$instiFK', '$staffFK')");
    $result = pg_query($sql);

那是我目前拥有的脚本,但它不起作用。关于如何解决这个问题的任何想法,以便当用户提交所有数据表时将被填充并强制执行参照完整性?我快到了,还在尝试,但无济于事。

错误信息:

 ERROR: invalid input syntax for integer: "Resource id #4" LINE 1: INSERT INTO isstaffof(i_id, s_id) VALUES ('Resource id #4', ...

如果您需要更多解释,请告诉我,但我确信它很清楚我想要实现的目标,并且我相信我可以在没有这么多pg_query电话的情况下做到这一点。

4

3 回答 3

1

从 PostgreSQL 版本 9.1 开始,您可以使用单个查询在所有 3 个表中插入一个可写的公共表表达式

WITH 
step_1 AS(
    INSERT INTO staff (name) VALUES('Frank') RETURNING s_id
),
step_2 AS (
    INSERT INTO institution (name) VALUES('PostgreSQL') RETURNING i_id
)
INSERT INTO isStaffOf (i_id, s_id) SELECT i_id,s_id FROM step_1, step_2;

简单、快速、可靠。

当某些记录已经存在并且只想选择主键值时,您也可以做一些其他技巧。

于 2012-09-06T07:53:32.963 回答
0

您必须使用pg_fetch_assoc或类似的东西来获取结果。您现在使用它的方式是将整个 pg_query 资源作为整数传递 - 显然 php 无法将其转换为有效整数。

$name = $_POST["name"];
$username = $_POST["username"];
$password = $_POST["password"];
$email = $_POST["email"];
$institution = $_POST["institution"];

$conn = pg_connect("host=***** port=**** dbname=****** user=**** password=******");
$staffWrite = pg_query("INSERT INTO staff(name, username, password, email) VALUES ('$name', '$username', '$password', '$email')");
$instiWrite = pg_query("INSERT INTO institution(name) VALUES ('$institution')");

$instiFK=pg_query("SELECT i_id FROM institution WHERE name='$institution'");
$rowInsti = pg_fetch_assoc($instiFK);
$staffFK = pg_query("SELECT s_id FROM staff WHERE name='$username'");
$rowStaff = pg_fetch_assoc($staffFK);

$result = pg_query("INSERT INTO isstaffof(i_id, s_id) VALUES (".$rowInsti['i_id'].", ".$rowStaff['s_id'].")");    

作为替代方案,您可以在每次插入后直接使用pg_last_oid来获取 id。(返回解决方案会更漂亮。只需阅读 php.net 页面上的评论)

于 2012-09-05T13:50:32.263 回答
0

在创建 isstaffof 表时,您至少必须指定数据类型,并且可以指定它们是外键。

CREATE TABLE isstaffof
    (i_id BIGINT REFERENCES institution(i_id)
    , s_id BIGINT REFERENCES staff(s_id)
    );

注意:避免使用 MixedCase 作为标识符。如果您必须移植到不同的 DBMS 平台,它可能会导致严重的问题。

更新:只要把它放在一个简单的INSERT INTO ... SELECT ... FROM ...声明中。

CREATE TABLE staff (s_id serial UNIQUE, sname varchar);
CREATE TABLE institution (i_id serial UNIQUE, iname varchar);
CREATE TABLE isstaffof
    (i_id BIGINT REFERENCES institution(i_id)
    , s_id BIGINT REFERENCES staff(s_id)
    );

INSERT INTO isstaffof(i_id,s_id)
SELECT i.i_id,s.s_id
FROM staff s, institution i
WHERE i.iname='$institution'
AND s.sname = '$staff'
        ;

现在,您可以将其包装到您的前端代码中。

于 2012-09-05T14:01:45.770 回答