使用外键写入数据表

时间:2012-09-05 12:52:14

标签: php postgresql

我有一个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电话,我就能做到。

3 个答案:

答案 0 :(得分:1)

从PostgreSQL版本9.1开始,您可以使用单个查询在所有3个表中进行INSERT,writable common table expression

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;

简单,快速,可靠。

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

答案 1 :(得分: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。 (RETURNING-solution会更漂亮。只需阅读php.net页面上的评论)

答案 2 :(得分: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'
        ;

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