我有一个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
电话,我就能做到。
答案 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'
;
现在,您可以将其包装到前端代码中。