postgresql - 如何从 postgres 存储函数读取 UDT

标签 postgresql stored-procedures jdbc user-defined-types

我似乎无法使用以下命令从存储的函数中正确读取 UDT postgres JDBC 驱动程序。这是一些示例代码:

CREATE TYPE u_country AS ENUM ('Brazil', 'England', 'Germany')

CREATE TYPE u_street_type AS (
  street VARCHAR(100),
  no VARCHAR(30)
)

CREATE TYPE u_address_type AS (
  street u_street_type,
  zip VARCHAR(50),
  city VARCHAR(50),
  country u_country,
  since DATE,
  code INTEGER
)

CREATE TABLE t_author (
  id INTEGER NOT NULL PRIMARY KEY,
  first_name VARCHAR(50),
  last_name VARCHAR(50) NOT NULL,
  date_of_birth DATE,
  year_of_birth INTEGER,
  address u_address_type
)

INSERT INTO t_author VALUES (1, 'George', 'Orwell',
TO_DATE('1903-06-25', 'YYYY-MM-DD'), 1903, ROW(ROW('Parliament Hill',
'77'), 'NW31A9', 'Hampstead', 'England', '1980-01-01', null))
INSERT INTO t_author VALUES (2, 'Paulo', 'Coelho',
TO_DATE('1947-08-24', 'YYYY-MM-DD'), 1947, ROW(ROW('Caixa Postal',
'43.003'), null, 'Rio de Janeiro', 'Brazil', '1940-01-01', 2))

CREATE FUNCTION p_enhance_address2 (address OUT u_address_type)
AS $$
BEGIN
        SELECT t_author.address
        INTO address
        FROM t_author
        WHERE first_name = 'George';
END;
$$ LANGUAGE plpgsql;

现在上面的代码在 postgres 中完美运行。我还可以选择 UDT 列 t_author.address 直接使用 SQL SELECT 语句。但当 我通过 JDBC 从存储的函数 p_enhance_address2 中进行选择,我得到了 奇怪的行为。我尝试了这两种调用方案:

connection.prepareStatement("select * from p_enhance_address2()");
connection.prepareCall("{ call p_enhance_address2(?) }"); 
// the latter with an output parameter registered

两种调用方案都会引发相同的行为(实际上 CallableStatement 只不过是从函数中进行选择)。 似乎存在两个截然不同的问题:

嵌套的 UDT 结构完全搞乱了获取结果。这 这是我通过 JDBC 得到的结果:

PreparedStatement stmt = connection.prepareStatement(
  "select * from p_enhance_address2()");
ResultSet rs = stmt.executeQuery();

while (rs.next()) {
  System.out.println("# of columns: " + 
    rs.getMetaData().getColumnCount());
  System.out.println(rs.getObject(1));
}

输出:

nr of columns: 6 ("(""Parliament Hill"",77)",NW31A9)

为什么有 6 列?以及为什么 UDT 被错误地获取(很多 缺少字段)

当嵌套 UDT 时,可以实现一点改进 u_street_type 被“扁平化”为 varchar,这导致 假设 JDBC 驱动程序对嵌套 UDT 的支持很差:

CREATE TYPE u_address_type AS (
  street VARCHAR(80),
  zip VARCHAR(50),
  city VARCHAR(50),
  country u_country,
  since DATE,
  code INTEGER
)

INSERT INTO t_author VALUES (1, 'George', 'Orwell',
TO_DATE('1903-06-25', 'YYYY-MM-DD'), 1903, ROW('Parliament Hill 77',
'NW31A9', 'Hampstead', 'England', '1980-01-01', null))
INSERT INTO t_author VALUES (2, 'Paulo', 'Coelho',
TO_DATE('1947-08-24', 'YYYY-MM-DD'), 1947, ROW('Caixa Postal 43.003',
null, 'Rio de Janeiro', 'Brazil', '1940-01-01', 2))

那么结果将是这样的:

nr of columns: 6 ("Parliament Hill 77",NW31A9,Hampstead,England,1980-01-01,)

UDT 记录现在看起来是正确的(从以下位置的结果集中获取) 位置1)。但结果集中仍然有 6 列。

一些事实:

  • 我在 pgAdmin III 中没有遇到这些问题
  • 我使用 PostgreSQL 9.0.1,由 Visual C++ build 1500 编译,64 位
  • 我使用 postgresql-9.0-801.jdbc4.jar

有人知道出了什么问题吗?

最佳答案

我可以重现这个,这似乎是一个错误。

我建议您将其发布到 PostgreSQL JDBC 邮件列表,以便开发人员可以修复此问题。

关于postgresql - 如何从 postgres 存储函数读取 UDT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4652651/

相关文章:

sql - 通过来自不同未链接表的不同字段的连续循环

带有本地化的 Postgresql 数据库创建问题

sql - 在存储过程中创建 SQL 表变量

java - 通过 JDBC 从 AWS Redshift 检索插入的标识值

java - java应用程序连接数据库的方式

mysql - 如何找出可能发生 COMMIT 的位置?

sql - Postgresql CASE 语法的问题

sql - 使用 AND 和 OR 通过查询检索多行

mysql - 获取错误到 : MySQL stored procedure with parameters in Access frontend via VBA

oracle - 从 JDBC 调用 Oracle 面向对象的 PL/SQL 成员过程