PostgreSQL建外键表时在REFERENCES附近报语法错误
错误产生原因
直接触发本次语法报错的核心原因是外键定义的语法格式错误:
- SQL标准中
FOREIGN KEY的定义语法为FOREIGN KEY (当前表外键字段名) REFERENCES 关联表名(关联表主键字段名),字段名部分的括号必须在写完字段名后立刻闭合。原代码中idcustomer的外键定义写成了FOREIGN KEY (idcustomer REFERENCES olap.customers(idcustomer),漏掉了idcustomer后面的右半括号,导致REFERENCES关键字被数据库解析到了外键字段的括号内部,直接抛出语法错误。 - 除了触发报错的括号问题,原SQL还存在两处隐藏问题,就算改完括号也可能执行失败:
- 关联时间维度表时写的是
REFERENCES time(idtime),没有指定schema前缀olap.,如果当前连接的默认schema不是olap,会报表不存在的错误。 - 预先创建的
olap.customers表主键定义本身存在语法冲突:PostgreSQL中SERIAL是整型自增类型,不能和varchar(10)类型同时声明,也不需要额外加autoincrement关键字,这张表在标准PostgreSQL环境下无法正常创建,且外键要求当前表字段类型和关联的主键字段类型必须完全一致,类型不匹配也会导致外键创建失败。
- 关联时间维度表时写的是
修正方案
- 补全
idcustomer外键定义中缺失的右括号,符合基础语法要求 - 给时间维度表的关联加上
olap.schema前缀,统一所有关联表的schema引用,避免schema查找错误 - 修正
olap.customers表的主键定义,保证字段类型和事实表的外键字段完全匹配:如果使用自增整型主键,就将idcustomer定义为SERIAL PRIMARY KEY,去掉冗余的varchar(10)和autoincrement声明,同时把事实表的idcustomer字段类型改为integer;如果业务要求idcustomer为字符串类型,就去掉SERIAL和autoincrement声明,保留varchar(10) PRIMARY KEY即可。
修正后可正常执行的SQL代码如下:
-- 若之前customers表创建失败,先执行修正后的维度表创建语句 CREATE TABLE olap.customers ( idcustomer SERIAL PRIMARY KEY, name varchar(40) NOT NULL, city varchar(40) NOT NULL, zip char(6) NOT NULL, address varchar(40) NOT NULL, email varchar(40), phone varchar(16) NOT NULL, regon char(9) ); -- 修正后的事实表创建语句 CREATE TABLE olap.fact( idtime integer NOT NULL, idaddressee integer NOT NULL, idcustomer integer NOT NULL, idfact integer NOT NULL, price numeric(7,2), PRIMARY KEY (idtime, idaddressee, idcustomer), FOREIGN KEY (idaddressee) REFERENCES olap.addressees(idaddressee), FOREIGN KEY (idcustomer) REFERENCES olap.customers(idcustomer), FOREIGN KEY (idtime) REFERENCES olap.time(idtime) );
注意:如果业务上
idcustomer需要使用字符串类型,只需要把两张表的idcustomer字段统一改为varchar(10)类型,去掉SERIAL自增属性即可。
内容的提问来源于stack exchange,提问作者Key_Keys
相关产品推荐
相关产品推荐

