使用postgresql 9.3我可以选择JSON数据类型的特定字段,但是如何使用UPDATE修改它们?我在postgresql文档中或在线任何地方都找不到任何这样的例子.我试过了明显的事:
postgres=# create table test (data json);
CREATE TABLE
postgres=# insert into test (data) values ('{"a":1,"b":2}');
INSERT 0 1
postgres=# select data->'a' from test where data->>'b' = '2';
?column?
----------
1
(1 row)
postgres=# update test set data->'a' = to_json(5) where data->>'b' = '2';
ERROR: syntax error at or near "->"
LINE 1: update test set data->'a' = to_json(5) where data->>'b' = '2...
Run Code Online (Sandbox Code Playgroud) 我在PostgreSQL中有这个功能,但我不知道如何返回查询结果:
CREATE OR REPLACE FUNCTION wordFrequency(maxTokens INTEGER)
RETURNS SETOF RECORD AS
$$
BEGIN
SELECT text, count(*), 100 / maxTokens * count(*)
FROM (
SELECT text
FROM token
WHERE chartype = 'ALPHABETIC'
LIMIT maxTokens
) as tokens
GROUP BY text
ORDER BY count DESC
END
$$
LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
但我不知道如何在PostgreSQL函数中返回查询结果.
我发现返回类型应该是SETOF RECORD
,对吗?但是返回命令不对.
这样做的正确方法是什么?
使用PostgreSQL,第一条记录的表中的列值存储在记录变量中.例如:让变量为:recordvar
recordvar.columnname
Run Code Online (Sandbox Code Playgroud)
给出指定列名的值.我将columname
在变量中定义:
var := columnname
Run Code Online (Sandbox Code Playgroud)
在地方columnname
,如果我与变量如更换recordvar.var
,这是行不通的.
请让我知道如何处理这种情况.以下是示例代码:
CREATE OR REPLACE FUNCTION getrowdata(id numeric, table_name character varying)
RETURNS SETOF void AS
$BODY$
DECLARE
srowdata record;
reqfield character varying;
value numeric;
BEGIN
RAISE NOTICE 'id: %',id;
reqfield:= 'columnname';
EXECUTE 'select * from datas.'||table_name||' WHERE id = '||id into srowdata;
RAISE NOTICE 'srowdata: %',srowdata;
RAISE NOTICE 'srowdatadata.columnname: %',srowdata.columnname;
value:= srowdata.reqfield;
RAISE NOTICE 'value: %',value;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
Run Code Online (Sandbox Code Playgroud) 我们编写了一个get_timestamp()
定义为的函数
CREATE OR REPLACE FUNCTION get_timestamp()
RETURNS integer AS
$$
SELECT (FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 10) - 13885344000)::int;
$$
LANGUAGE SQL;
Run Code Online (Sandbox Code Playgroud)
这在INSERT和UPDATE上用于输入或编辑数据库记录中已创建和已修改字段中的值.但是,我们发现连续添加或更新记录时它返回的值相同.
在检查pgAdmin III中的函数时,我们注意到在运行SQL来构建函数时,在LANGUAGE SQL语句之后注入了关键字IMMUTABLE.该文件指出默认是挥发性的(如果一个都没有出现,VOLATILE是默认的假设),所以我不知道为什么IMMUTABLE注射,然而,改变这种稳定解决了重复值的问题.
注意:如接受的答案中所述,IMMUTABLE永远不会被pgAdmin或Postgres添加到函数中,并且必须在开发期间添加.
我猜测正在发生的事情是这个函数正在被评估并且结果被缓存用于优化,因为它被标记为IMMUTABLE指示Postgres引擎在给定相同(空)参数列表的情况下返回值不应该改变.但是,当在触发器中未使用时,直接在INSERT语句中使用时,该函数将返回一个不同的值五次,然后再返回相同的值.这是由于某些优化算法会出现类似"如果在会话中多次使用IMMUTABLE函数5次,请将结果缓存以供将来调用"?
关于如何在Postgres函数中使用这些关键字的任何说明将不胜感激.对于我们来说STABLE是正确的选择,因为我们在触发器中使用了这个函数,或者还有更多要考虑的东西,例如文档说:
(对于希望查询当前命令修改的行的AFTER触发器不合适.)
但我并不清楚原因.
我需要RECORD
按键/索引遍历类型项,就像我可以使用其他编程语言中的数组结构一样.
例如:
DECLARE
data1 record;
data2 text;
...
BEGIN
...
FOR data1 IN
SELECT
*
FROM
sometable
LOOP
FOR data2 IN
SELECT
unnest( data1 ) -- THIS IS DOESN'T WORK!
LOOP
RETURN NEXT data1[data2]; -- SMTH LIKE THIS
END LOOP;
END LOOP;
Run Code Online (Sandbox Code Playgroud) 我是 Postgresql 新手,所以如果我的问题没有意义,请原谅。
我正在尝试找到一种方法将我的数据库结构迁移到Postgresql,特别是,我发现函数非常方便,并且希望使我的众多触发器更容易编写。
在我的数据库中,我使用标准last_modified
和last_modified_by
字段来跟踪更改。我还使用带有增量序列的标准主键。
有内置语法可将序列链接到主键 ID,但由于last_modified
无论如何我都必须为字段编写触发器,所以我想知道是否可以有一个通用函数来一次更新所有内容。
示例:表ANIMAL
有字段AMIMAL_ID
(主键,带有序列SEQ_ANIMAL
)、字段LAST_MODIFIED
和LAST_MODIFIED_BY
。
同样,我有一个PLANT
包含字段PLANT_ID
(主键,带有序列SEQ_PLANT
)、字段LAST_MODIFIED
等等的表LAST_MODIFIED_BY
。
我想创建一个通用函数,在我需要创建的 4 个触发器中调用。我希望得到这样的东西:
插入函数之前:
CREATE FUNCTION TRIGGER_BI(p_pkField text, p_Sequence text) RETURNS TRIGGER AS $$
DECLARE
curtime timestamp := now();
BEGIN
NEW.LAST_UPDATED := curtime;
NEW.LAST_UPDATED_BY := current_user;
NEW.p_pkField := nextval(p_Sequence);
END;
$$
LANGUAGE 'plpgsql' IMMUTABLE
SECURITY DEFINER;
Run Code Online (Sandbox Code Playgroud)
更新前功能:
CREATE FUNCTION TRIGGER_BU() RETURNS TRIGGER AS $$
DECLARE …
Run Code Online (Sandbox Code Playgroud) 是否有一种简单的(即非hacky)和无竞争条件的方法来在PostgreSQL中创建分区序列.例:
在问题中使用正常序列:
| Project_ID | Issue |
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
| 2 | 4 |
Run Code Online (Sandbox Code Playgroud)
在问题中使用分区序列:
| Project_ID | Issue |
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 2 |
Run Code Online (Sandbox Code Playgroud) 我正在尝试创建一个函数,该函数将采用通用表并将 N 列转换为大写。我没有找到此类问题的解决方案,但我能够提出以下建议:
create or replace function uc_on_insert()
returns trigger as
$$
declare
p_tbl varchar = TG_TABLE_NAME;
p_sch varchar = TG_TABLE_SCHEMA;
i varchar;
begin
for i in
(select column_name
from INFORMATION_SCHEMA.COLUMNS
where 1=1
and table_name ilike p_tbl
and table_schema ilike p_sch
and data_type ='character varying')
loop
execute 'new.' || i || ' = upper(new.' || i || ');';
return new;
end loop;
end;
$$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)
我目前收到此错误:
ERROR: syntax error at or near "new"
LINE 1: new.c1 = upper(new.c1);
^ …
Run Code Online (Sandbox Code Playgroud) 我想从导入PostgreSQL 9.3.5的OpenStreetMap数据库中检索具有给定名称的方法,操作系统是Win7 64位.为了有点容错,我使用了Postgres的unaccent扩展.
我的查询如下:
SELECT * FROM germany.ways
WHERE lower(tags->'name') like lower(unaccent('unaccent','Weststrasse'))
Run Code Online (Sandbox Code Playgroud)
查询计划:
Seq Scan on ways (cost=0.00..2958579.31 rows=122 width=465)
Filter: (lower((tags -> 'name'::text)) ~~ lower(unaccent('unaccent'::regdictionary, 'Weststrasse'::text)))
Run Code Online (Sandbox Code Playgroud)
奇怪的是,此查询使用顺序扫描方式,尽管索引存在于lower(tags->'name')
:
CREATE INDEX ways_tags_name ON germany.ways (lower(tags -> 'name'));
Run Code Online (Sandbox Code Playgroud)
一旦我从查询中删除unaccent,Postgres就会使用索引:
SELECT * FROM germany.ways
WHERE lower(tags->'name') like lower('Weststrasse')
Run Code Online (Sandbox Code Playgroud)
查询计划:
Index Scan using ways_tags_name on ways (cost=0.57..495.43 rows=122 width=465)
Index Cond: (lower((tags -> 'name'::text)) = 'weststrasse'::text)
Filter: (lower((tags -> 'name'::text)) ~~ 'weststrasse'::text)
Run Code Online (Sandbox Code Playgroud)
为什么无法防止Postgres使用索引?在我看来,这没有意义,因为在执行实际查询之前,应该已经完全知道unaccent(变音符号删除等)的结果.所以Postgres应该能够使用索引.使用unaccent时如何避免seq扫描?
我正在创建一个触发器,该触发器为列使用动态名称
NEW.name:=2222; -- works fine !
Run Code Online (Sandbox Code Playgroud)
但
dynamic_column:='name';
EXECUTE '$1.'||dynamic_column||':=2222 ' USING NEW; -- raises error
Run Code Online (Sandbox Code Playgroud)
给出一个错误:
错误:“ $ 1”或附近的语法错误LINE 1:$ 1.name:= 2222
问题:如何在存储函数中声明相同类型的变量参数?
简单的答案是使用%TYPE
,这有效:
CREATE OR REPLACE FUNCTION test_function_1(param1 text)
RETURNS integer AS
$BODY$
DECLARE
myVariable param1%TYPE;
BEGIN
return 1;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Run Code Online (Sandbox Code Playgroud)
但问题是何时param1
是复合类型:
CREATE TYPE comp_type as
(
field1 text
)
CREATE OR REPLACE FUNCTION test_function_2(param1 comp_type)
RETURNS integer AS
$BODY$
DECLARE
myVariable param1%TYPE;
BEGIN
return 1;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Run Code Online (Sandbox Code Playgroud)
这不起作用:
ERROR: type comp_type does not exist [SQL State=42704]
Run Code Online (Sandbox Code Playgroud)
那么当param1
复合型时我该怎么办?
(注意:myVariable comp_type
因为我的功能稍微复杂一点, …
我已经找到了我要在Oracle和SQL Server上解决的问题的解决方案(我认为),但是似乎无法将其转换为Postgres解决方案。我正在使用Postgres 9.3.6。
这个想法是为了生成用于分析目的的有关表内容的“元数据”。这只能通过让每一列都运行查询来找出(例如...)最小/最大/计数值等来完成(AFAIK)。为了使过程自动化,最好让数据库生成查询,然后执行查询。
使用示例salesdata
表,我可以使用以下代码段为每列生成一个选择查询,并返回min()值:
SELECT 'SELECT min('||column_name||') as minval_'||column_name||' from salesdata '
FROM information_schema.columns
WHERE table_name = 'salesdata'
Run Code Online (Sandbox Code Playgroud)
优点是,无论列数如何,数据库都会生成代码。现在,我想到了无数个地方来存储这些查询,这些查询可以是某种变量,也可以是表列,其想法是执行这些查询。我想将生成的查询存储在变量中,然后使用EXECUTE
(或EXECUTE IMMEDIATE
)语句执行它们,这是此处采用的方法(请参见右窗格),但是Postgres不会让我在函数外部声明变量,因此我一直在抓挠我对如何将它们组合在一起,无论是什至是遵循的方向,也许还有更简单的东西。
您有任何指点吗,由于其他问题,我目前正在尝试类似的方法,但不知道我是否朝着正确的方向前进:
CREATE OR REPLACE FUNCTION foo()
RETURNS void AS
$$
DECLARE
dyn_sql text;
BEGIN
dyn_sql := SELECT 'SELECT min('||column_name||') from salesdata'
FROM information_schema.columns
WHERE table_name = 'salesdata';
execute dyn_sql
END
$$ LANGUAGE PLPGSQL;
Run Code Online (Sandbox Code Playgroud) postgresql dynamic-sql plpgsql aggregate-functions dynamic-queries
我的PostgreSQL数据库包含一个用于存储已注册实体实例的表.此表格通过电子表格上传填充.Web界面允许操作员修改所呈现的信息.但是,原始数据不会被修改.所有的改变都存储在一个单独的表changes
与列unique_id
,column_name
,value
和updated_at
.
更改完成后,首先查询原始表,然后查询更改表(使用实例ID和最新更改日期,按列名称分组),将其呈现给操作员.这两个结果在PHP中合并,并在Web界面上显示.这是执行任务的一种相当严格的方式,我想将所有逻辑保留在SQL中.
我可以使用以下查询轻松选择表的最新更改:
SELECT fltr_chg.unique_id, fltr_chg.column_name, chg_val.value
FROM changes AS chg_val
JOIN (
SELECT chg_rec.unique_id, chg_rec.column_name, MAX( chg_rec.updated_at )
FROM information_schema.columns AS source
JOIN changes AS chg_rec ON source.table_name = 'instances'
AND source.column_name = chg_rec.column_name
GROUP BY chg_rec.unique_id, chg_rec.column_name
) AS fltr_chg ON fltr_chg.unique_id = chg_val.unique_id
AND fltr_chg.column_name = chg_val.column_name;
Run Code Online (Sandbox Code Playgroud)
从instances
表中选择条目同样简单:
SELECT * FROM instances;
Run Code Online (Sandbox Code Playgroud)
现在,如果只有一种方法可以转换前一个结果并将结果值替换为后者,基于unique_id
和column_name
,并且仍将结果保留为表格,则问题将得到解决.这可能吗?
我确信这不是最罕见的问题,而且很有可能,某些系统会以类似的方式跟踪数据的变化.如果不是通过上述方法之一(当前和寻求的解决方案),他们如何将它们应用于数据?
postgresql ×13
plpgsql ×8
dynamic-sql ×4
types ×3
sql ×2
triggers ×2
crosstab ×1
database ×1
for-loop ×1
function ×1
hstore ×1
indexing ×1
json ×1
loops ×1
partitioning ×1
php ×1
polymorphism ×1
primary-key ×1
record ×1
return ×1
return-type ×1
sequence ×1
timestamp ×1
unaccent ×1
volatility ×1