Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 以文本字符串形式访问给定字段名的postgres字段_Postgresql - Fatal编程技术网

Postgresql 以文本字符串形式访问给定字段名的postgres字段

Postgresql 以文本字符串形式访问给定字段名的postgres字段,postgresql,Postgresql,我在postgres有一个表: create table fubar ( name1 text, name2 text, ..., key integer); 我想编写一个函数,在给定列名的情况下从fubar返回字段值: function getFubarValues(col_name text, key integer) returns text ... 其中,getFubarValues返回键标识的行中指定列的值。看起来这应该很容易 我不知所措。有人能帮忙吗?谢谢。您可以使用动态SQL按

我在postgres有一个表:

create table fubar (
name1 text,
name2 text, ...,
key integer);
我想编写一个函数,在给定列名的情况下从fubar返回字段值:

function getFubarValues(col_name text, key integer) returns text ...
其中,getFubarValues返回键标识的行中指定列的值。看起来这应该很容易


我不知所措。有人能帮忙吗?谢谢。

您可以使用动态SQL按名称选择列:

create or replace function get_fubar_values (col_name text, row_key integer) 
returns setof text language plpgsql as $$begin
    return query execute 'select ' || quote_ident(col_name) || 
      ' from fubar where key = $1' using row_key;
end$$;
Klin的回答是一个很好的(即安全的)解决问题的方法,但可以简化:

PostgreSQL的
->
运算符允许表达式。例如:

CREATE TABLE test (
    id SERIAL,
    js JSON NOT NULL,
    k TEXT NOT NULL
);
INSERT INTO test (js,k) VALUES ('{"abc":"def","ghi":"jkl"}','abc');
SELECT js->k AS value FROM test;
产生

 value
-------
 "def"
因此,我们可以将其与
行到行json
相结合:

CREATE TABLE test (
    id SERIAL,
    a TEXT,
    b TEXT,
    k TEXT NOT NULL
);
INSERT INTO test (a,b,k) VALUES
    ('foo','bar','a'),
    ('zip','zag','b');
SELECT row_to_json(test)->k AS value FROM test;
产生:

 value 
-------
 "foo"
 "zag"
在这里,我从表本身获取键,但当然可以从任何源/表达式获取。这只是一个价值。还要注意,返回的结果是一个JSON值类型(它不知道是文本、数字还是布尔值)。如果希望它是文本,只需将其强制转换为:
(row\u to\u json(test)->k)::text


现在问题本身已经得到了回答,下面是为什么你不应该这样做,以及你应该做什么! 永远不要相信任何数据。即使它已经存在于您的数据库中,您也不应该相信它。我在这里发布的方法是安全的,可以抵御SQL注入攻击,但是攻击者仍然可以将
k
设置为
'id'
,并看到一列他们不想看到的内容

一种更好的方法是在考虑这种查询的情况下构造数据。Postgres为此提供了一些优秀的数据类型;HSTORE和JSON/JSONB。将动态列合并到一个具有这些类型之一的列中(我建议HSTORE更简单、更完整)

这有几个优点:您的模式定义良好,如果添加更多的动态列,则不需要更改,不需要执行昂贵的重新转换(即
行到行json
),并且可以利用列上的索引(多亏了PostgreSQL的功能索引)

与我上面写的代码等效的代码是:

CREATE EXTENSION HSTORE; -- necessary if you're not already using HSTORE
CREATE TABLE test (
    id SERIAL,
    cols HSTORE NOT NULL,
    k TEXT NOT NULL
);
INSERT INTO test (cols,k) VALUES
    ('a=>"foo",b=>"bar"','a'),
    ('a=>"zip",b=>"zag"','b');
SELECT cols->k AS value FROM test;
或者,为了在插入时自动转义值,可以使用以下方法之一:

INSERT INTO test (cols,k) VALUES
    (hstore( 'a', 'foo' ) || hstore( 'b', 'bar' ), 'a'),
    (hstore( ARRAY['a','b'], ARRAY['zip','zag'] ), 'b');

有关更多详细信息,请参阅。

“这将从给定列名的fubar返回字段值”-为什么不能直接编写
从fubar选择列名?您在这里试图解决的真正问题是什么?这可能比Kill的答案要快,但OP应该注意,在使用此方法之前,他们必须注意列名是安全的(任何空格、引号或其他特殊字符都会将其打断,如果col_name输入不可信(即,它来自用户或数据库本身,这在本问题的上下文中似乎很可能),则这是SQL注入风险)