【问题标题】:PostgreSQL declaring variables with explicit data typesPostgreSQL 声明具有显式数据类型的变量
【发布时间】:2014-09-06 02:02:06
【问题描述】:

我已经阅读了文档和几篇 SO 帖子,但仍然不清楚如何在 Postgres 中声明和分配变量...这是我最初尝试做的:

SET SEARCH_PATH = PsychoProductions;
declare var_person_id   INT;
select var_person_id = (
        select id 
        from person 
        where 
                first_name = prm_first_name AND
                last_name = prm_last_name AND
                organization = prm_organization
        );
/* 
Result:
ERROR:  syntax error at or near "INT"
LINE 2:     DECLARE var_person_id   INT;
                                    ^

********** Error **********

ERROR: syntax error at or near "INT"
SQL state: 42601
Character: 70
*/

这很简单,但它不起作用......我对 Postgres 语法有点陌生,我希望能得到一些帮助来解决这个问题,因为我想显式声明数据类型,如果可能的话,在将数据设置为变量之前。

你们有谁知道我在设置变量时显式声明数据类型缺少什么?

编辑 1:09-05-2013

有些人指出必须在函数中使用变量。我不认为 Postgres 完全是这种情况(我知道 MySQL 是这样,而不是 T-SQL),但重点是,这里是上面的代码,在函数的上下文中。我将很快测试一个答案中指出的内容,并相应地接受。所以这里是到目前为止的完整代码:

set search_path = PsychoProductions;
create or replace function fcn_Insert_person (
        -- "person" table
        prm_role_id             text, -- table default 'Customer'
        prm_first_name          text,
        prm_last_name           text,
        prm_organization        text,
        prm_website             text,
        prm_default_Billing_Method_ID   text, -- table default 'Net 30'
        prm_active              BOOLEAN,
        -- "address" table
        prm_address_type_id     text, -- table default 'Unique'
        prm_address             text,
        prm_city                text,
        prm_state               text,
        prm_zip_code            text,
        -- "email" table
        prm_email_address       text,
        prm_email_type_id       text, -- table default 'Business'
        -- "phone" table
        prm_phone_number        text,
        prm_phone_type_id       text  -- table default 'Main'
        ) 
        returns setof Person 
as

$delimiter$

begin
set search_patch = PsychoProductions;
start transaction;
insert into person (
        role_id,
        first_name,
        last_name,
        organization,
        website,
        default_billing_method_id,
        active
        )
values (
        prm_role_id,
        prm_first_name,
        prm_last_name,
        prm_organization,
        prm_website,
        prm_default_Billing_Method_ID,
        prm_active
        );
commit; 

start transaction;
declare var_person_id   int;
select var_person_id = (
        select id 
        from person 
        where 
                first_name = prm_first_name AND
                last_name = prm_last_name AND
                organization = prm_organization
        );
-- and this is where I got stuck

编辑 2:09-06-2013

我使用了select into myVar ... 语法,但现在我遇到了一个完全不同的问题...我应该问一个新问题吗?

错误:

ERROR:  column "var_person_id" does not exist
LINE 81:         var_person_id,
                 ^
********** Error **********

ERROR: column "var_person_id" does not exist
SQL state: 42703
Character: 2220

代码:

start transaction;
-- declare var_person_id   int;
select id into var_person_id 
        from person 
        where 
                first_name = prm_first_name AND
                last_name = prm_last_name AND
                organization = prm_organization;

insert into address (
        person_id,
        address_type_id,
        address,
        city,
        state,
        zip_code
        )
values (
        var_person_id, -- error here
        prm_address_type_id,
        prm_address,
        prm_city,
        prm_state,
        per_zip_code
        );

【问题讨论】:

  • 正如 Dwayne 所指出的,变量只能在过程代码中使用。但是你为什么需要那个?如果您想稍后重新使用该选择的结果,您可以使用子选择来做到这一点。如果您多次需要它,请使用公用表表达式。也许您应该向我们展示您的真正问题。
  • 我添加了代码上下​​文,谢谢@a_horse_with_no_name - 你认为我只是停留在 T-SQL 思维中并且有更自然的方法可以做到这一点吗?
  • 所以您正在尝试检索由insert 生成的id?如果是这样,请使用insert ... values () returning id 或使用currval()lastval() 在后续语句中访问最后生成的序列值。或者使用数据修改 CTE 的组合
  • 我是,你的建议可能会奏效......但是,一般来说,如果变量很难在 Postgres 中使用,它们到底有什么用处??
  • 我不明白使用它们有什么困难。它们以与任何编程语言相同的方式有用。但是您只能在 程序 中使用它们,即存储函数(这与 Oracle、DB2、Firebird 和许多其他 DBMS 没有什么不同)。我仍然认为您以错误的方式处理问题。而不是问“我如何使用变量”,您应该解释您的 real 问题。我很确定有一个更好的解决方案,即坚持以不应该的方式使用变量。

标签: sql postgresql variables


【解决方案1】:

您只能在函数(存储过程)中声明变量。试试这样的:

CREATE FUNCTION my_func(prm_first_name text,prm_last_name text) 
RETURNS SET OF int $$
DECLARE
    var_person_id int;
BEGIN
    SELECT id INTO var_person_id
        FROM person,var_parameter
        WHERE first_name = prm_first_name 
        AND last_name = prm_last_name
        AND organization = prm_organization;

    -- OR

    var_person_id := (SELECT id FROM ...);

    -- use it later like this:

    RETURN QUERY SELECT ... FROM ... WHERE id=var_person_id;
END;
$$ LANGUAGE PLPGSQL;

【讨论】:

  • 但您从未演示过使用 var_person_id 变量。
  • @DwayneTowell 我将其余代码添加为编辑,我一直在尝试在函数中声明。我对你的方法的唯一问题是SELECT ... INTO myVar 推断数据类型,而不是明确声明它,这就是我想要做的......但是如果有更多“Postgres”的方式来做到这一点,我是开放的。我想我暂时陷入了 T-SQL/MySQL 模式,可能没有掌握 Postgres 的核心概念......
  • @Phrancis:“推断数据类型”是什么意思。您使用的任何变量都必须使用数据类型声明。 PL/pgSQL 是一种强类型语言(就像 SQL 一样)。你不能声明没有类型的变量。指定类型应该不是问题,因为您选择的列也有类型。变量需要具有相同(或兼容)的类型。
  • 我正在尝试在变量上显式声明数据类型;如果我告诉引擎这个变量应该是int 而不是通过'foo' 它不会接受它...
  • @Phrancis:你当然不能。 'foo' 是字符文字而不是整数。那么,到底为什么要将字符值存储到定义为数字的变量中呢? Dwayne 的回答清楚地向您展示了如何做您显然想做的事情。
猜你喜欢
  • 2018-12-09
  • 1970-01-01
  • 1970-01-01
  • 2018-12-16
  • 2017-04-07
  • 1970-01-01
  • 1970-01-01
  • 2019-01-12
  • 1970-01-01
相关资源
最近更新 更多