[英]how to deal with single quotation marks in postgresql functions
我有一個pg函數,需要用單引號引起來。
create or replace function deal_null_value(in user_id numeric) returns integer as
$body$
declare
part_num integer;
sql_str character varying;
begin
sql_str := '
select b.num from (
select regexp_split_to_table(together,E',\\s*') as together,
count(id) as num
from inc_info t
where
t.registime>=to_timestamp('2011-10-01 00:00:00','yyyy-MM-dd HH:mi:ss')
and t.registime<=to_timestamp('2011-10-31 23:59:59','yyyy-MM-dd HH:mi:ss')
group by together_person
) as b
where cast(b.together as integer) = ' || user_id;
EXECUTE sql_str into part_num;
return part_num;
end;
$body$
LANGUAGE 'plpgsql'
您會看到我有一些單引號。
regexp_split_to_table(together,E',\\s*')
to_timestamp('2011-10-01 00:00:00','yyyy-MM-dd HH:mi:ss')
我想使用$$代替',並且想使用quote_literal函數,該如何使用?
提前致謝!
@Mu已經回答了有關報價的問題,@ araqnid清除了鑄造問題。 還有許多問題需要其他答案。 嘗試這個:
CREATE OR REPLACE FUNCTION deal_null_value(IN user_id numeric, OUT part_num integer)
AS
$body$
DECLARE
sql_str text;
BEGIN
sql_str := $x$
SELECT b.num FROM (
SELECT regexp_split_to_table(together, ',') AS together_person
,count(*)::integer as num
FROM inc_info t
WHERE registime >= '2011-10-01 00:00:00'::timestamp
AND registime < '2011-11-01 00:00:00'::timestamp
GROUP BY together_person
) b
WHERE b.together::numeric = $1
$x$;
EXECUTE sql_str
INTO part_num
USING user_id;
END;
$body$
LANGUAGE 'plpgsql';
這是非法的,並且會引發錯誤:
to_timestamp('2011-10-01 00:00:00','yyyy-MM-dd HH:mi:ss')
它必須是:
to_timestamp('2011-10-01 00:00:00','yyyy-MM-dd HH24:mi:ss')
但最好簡化為:
'2011-10-01 00:00:00'::timestamp
ISO 8601時間戳格式在任何語言環境中均有效 。 無需說明格式,這是標准。
更換
registime <= '2011-10-31 23:59:59'::timestamp
與
registime < '2011-11-01 00:00:00'::timestamp
時間戳記可以包含小數秒。 你會想念像
'2011-10-31 23:59:59.034'::timestamp
...很難找出原因。
簡化
regexp_split_to_table(together,E',\\\\s*') as together
至
regexp_split_to_table(together, ',') AS together
另外,我懷疑你想稱呼它
regexp_split_to_table(together, ',') AS together_person
當您進一步分組時。 您稍后將其轉換為數字(或整數)。 在這兩個轉換中, 前導/尾隨空白都會自動修剪 。 因此,不需要轉義序列或更復雜的正則表達式。 更快,更干凈。
如果 id不為空(如我所假設), 則使用 count(*)
代替count(id)
)。 count(*)
更快。
聚合函數count()
返回bigint
。 它轉換為integer
如您返回整數。 這里沒有問題,因為它是自動投射的,但在其他情況下可能會成為問題。
對part_num
使用OUT參數可以簡化代碼。 然后,在分配給part_num
,您不需要顯式的RETURN
語句。
為什么將b.together
為integer
? 您將其與numeric
user_id
進行比較? 也可以將user_id
integer
,或者將其user_id
為numeric
!
count(*)
vs.count count(col)
1)考慮一下: count(*)
僅檢查行的存在,而count(col)
也必須檢查col
是否為NULL
。 ( NULL值不計算在內! )
2)嘗試使用任何大桌子:
`EXPLAIN ANALYZE SELECT count(*) from tbl`
與
`EXPLAIN ANALYZE SELECT count(col) from tbl`.
如果列col
被定義為NOT NULL
或您知道 ,則不能有NULL值,那么count(*)
產生的結果與count(col)
。 在這種情況下使用count(*)
更快一些。
美元報價非常簡單:只需選擇一個令牌(可選),將其放在美元符號( $token$
)之間,然后像引用一樣使用它:
sql_str := $sql$
select b.num from (
select regexp_split_to_table(together,E',\\s*') as together,
count(id) as num
from inc_info t
where
t.registime>=to_timestamp('2011-10-01 00:00:00','yyyy-MM-dd HH:mi:ss')
and t.registime<=to_timestamp('2011-10-31 23:59:59','yyyy-MM-dd HH:mi:ss')
group by together_person
) as b
where cast(b.together as integer) = $sql$ || user_id;
您可以像其他任何字符串函數一樣使用quote_literal
:
where cast(b.together as integer) = cast($sql$ || quote_literal(user_id) || $sql$ as integer)$sql$;
盡管您的user_id
是數字,所以您可能不需要它。 太太,我認為這不會造成傷害。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.