所以我试图将临时表中的值复制到一个带有数组类型的表中,我得到以下错误,我无法找到克服的方法。
ERROR: cannot assign to field "addressid" of column "address" because its type addresstype[] is not a composite type
LINE 32: ...nID,Person.Title,Person.FirstName,Person.LastName,Person.Add...
^
********** Error **********
ERROR: cannot assign to field "addressid" of column "address" because its type addresstype[] is not a composite type
SQL state: 42804
这是我尝试的查询:
INSERT INTO Customer (CustomerID,Person.PersonID,Person.Title,Person.FirstName,Person.LastName,Person.Address.AddressID,Person.Address.AddressLine1,Person.Address.AddressLine2,Person.Address.City,Person.Address.PostalCode)
SELECT TCustomer.CustomerID,TPerson.PersonID,TPerson.Title,TPerson.FirstName,TPerson.LastName,TAddress.AddressID,TAddress.AddressLine1,TAddress.AddressLine2,TAddress.City,TAddress.PostalCode
FROM TCustomer,TPerson,TPersonAddress,TAddress
WHERE TCustomer.PersonID = TPerson.PersonID
AND TPerson.PersonID = TPersonAddress.PersonID
AND TPersonAddress.AddressID = TAddress.AddressID;
表&安培;类型:
CREATE TYPE AddressType AS(
AddressID integer,
AddressLine1 text,
AddressLine2 text,
City text,
PostalCode text);
CREATE TYPE PersonType AS(
PersonID integer,
Title text,
FirstName text,
LastName text,
Address AddressType[]);
CREATE TABLE Customer(
CustomerID integer,
Person PersonType,
PRIMARY KEY(CustomerID));
CREATE TEMPORARY TABLE TAddress (AddressID integer,AddressLine1 text,AddressLine2 text,City text,PostalCode text);
CREATE TEMPORARY TABLE TPerson (PersonID integer,Title text,FirstName text,LastName text);
CREATE TEMPORARY TABLE TCustomer (CustomerID integer,PersonID integer);
CREATE TEMPORARY TABLE TPersonAddress (PersonID integer,AddressID integer);
临时表已从CSV文件复制数据。 问题是每个人可以拥有许多不同的地址。 所以我必须将所有地址加载到AddressType数组。 但现在这似乎是不可能的,我无法找到处理阵列的方法。
我在互联网上找到的所有处理阵列的是:
INSERT INTO aa VALUES (3, ARRAY[ARRAY[1,2],ARRAY[3,4]]);
INSERT INTO sal_emp
VALUES ('Bill',
'{10000, 10000, 10000, 10000}',
'{{"meeting", "lunch"}, {"training", "presentation"}}');
然而这些例子只是添加了对我的案例毫无帮助的指定值。那么如何让它复制值: TAddress.AddressID,TAddress.AddressLine1,TAddress.AddressLine2,TAddress.City,TAddress.PostalCode
到数组:
Person.Address.AddressID,Person.Address.AddressLine1,Person.Address.AddressLine2,Person.Address.City,Person.Address.PostalCode
如果它是同一个人,则必须将所有地址添加到同一个数组中。
答案 0 :(得分:3)
虽然可以像这样分配复合/行类型的子字段:
CREATE TYPE foo AS (a int, b text);
CREATE TABLE bar (c int, f foo);
两者都有效:
INSERT INTO bar(a,b) SELECT 1, '(1,foo)';
INSERT INTO bar(a,b.a, b.b) SELECT 2, 2, 'bar';
对于数组,不也是如此(因此对于复合类型的数组也是如此)。
CREATE TABLE baz (a int, b foo[]);
不可能:
INSERT INTO baz(a,b.a, b.b) SELECT 2, 2, 'bar';
必须是以下之一:
INSERT INTO baz(a,b) SELECT 1, '{"(1,foo)"}';
INSERT INTO baz(a,b) SELECT 1, ARRAY['(1,foo)'];
我将使用规范化表格建议完全重新设计。
复合类型的数组非常笨重,不保存任何磁盘空间,禁用索引或关系完整性的许多核心功能,并且实际上是对Postgres提供的选项的一种奇特使用。
我 不 使用复合列类型。我知道你评论说你“需要”这样做,但我不明白这一点。仅仅因为可以做到这一点,并不意味着它应该完成。请改用或多或少的规范化表格。两个表的简单案例:
CREATE TABLE person (
person_id serial PRIMARY KEY
, title text
, firstname text
, lastname text
);
CREATE TABLE address (
address_id serial PRIMARY KEY
, person_id int REFERENCES person
, addressline1 text
, addressline2 text
, city text
, postalcode text
);
一个人可以拥有多个地址,一个地址属于一个person
。实际上,地址由多个人使用,但是冗余地添加一些地址通常更简单。如果您有许多这样的人,请使用带有附加表person_address
的多对多实现。详情如下:
答案 1 :(得分:0)
至少在PostgreSQL 10上,您可以这样做:
CREATE TYPE Child AS ( Name VARCHAR(10), Age INTEGER );
CREATE TABLE Father ( Name VARCHAR(10), Children Child[] );
INSERT INTO Father(Name, Children) VALUES (
'Thanos',
ARRAY[
('Nebula', 25)::Child,
('Gamora', 28)::Child
]
)
此解决方案的优点是,如果您的VARCHAR
中有TYPE
,则无需处理转义序列。