我想移植下面的SQL代码从MS SQL服务器到PostgreSQL。
DECLARE @iStartYear integer
DECLARE @iStartMonth integer
DECLARE @iEndYear integer
DECLARE @iEndMonth integer
SET @iStartYear = 2012
SET @iStartMonth = 4
SET @iEndYear = 2016
SET @iEndMonth = 1
;WITH CTE
AS
(
SELECT
--@iStartYear AS TheStartYear
@iStartMonth AS TheRunningMonth
,@iStartYear AS TheYear
,@iStartMonth AS TheMonth
UNION ALL
SELECT
--CTE.TheStartYear AS TheStartYear
--@iStartYear AS TheStartYear
CTE.TheRunningMonth + 1 AS TheRunningMonth
--,CTE.TheStartYear + (CTE.TheRunningMonth / 12) AS TheYear
,@iStartYear + (CTE.TheRunningMonth / 12) AS TheYear
,(CTE.TheMonth + 1 -1) % 12 + 1 AS TheMonth
FROM CTE
WHERE (1=1)
AND
(
CASE
--WHEN (CTE.TheStartYear + (CTE.TheRunningMonth / 12) ) < @iEndYear
WHEN (@iStartYear + (CTE.TheRunningMonth / 12) ) < @iEndYear
THEN 1
--WHEN (CTE.TheStartYear + (CTE.TheRunningMonth / 12) ) = @iEndYear
WHEN (@iStartYear + (CTE.TheRunningMonth / 12) ) = @iEndYear
THEN
CASE
WHEN ( (CTE.TheMonth + 1 -1) % 12 + 1 ) <= @iEndMonth
THEN 1
ELSE 0
END
ELSE 0
END = 1
)
)
SELECT * FROM CTE
这是我目前掌握的情况。
DO $$
DECLARE r record;
DECLARE i integer;
DECLARE __iStartYear integer;
DECLARE __iStartMonth integer;
DECLARE __iEndYear integer;
DECLARE __iEndMonth integer;
DECLARE __mytext character varying(200);
BEGIN
i:= 5;
--RAISE NOTICE 'test'
--RAISE NOTICE 'test1' || 'test2';
__mytext := 'Test message';
--RAISE NOTICE __mytext;
RAISE NOTICE '%', __mytext;
RAISE NOTICE '% %', 'arg1', 'arg2';
--SQL Standard: "CAST( value AS text )" [or varchar]
--PostgreSQL short-hand: "value::text"
__mytext := 'Test ' || i::text;
RAISE NOTICE '%', __mytext;
__mytext := 'mynumber: ' || CAST(i as varchar(33)) || '%';
RAISE NOTICE '%', __mytext;
__iStartYear := 2012;
__iStartMonth := 4;
__iEndYear := 2016;
__iEndMonth := 1;
--PERFORM 'abc';
SELECT 'abc';
-- SELECT __iStartMonth AS TheRunningMonth;
-- RAISE NOTICE 'The raise_test() function began.' + CAST( i AS text ) ;
-- FOR r IN SELECT table_schema, table_name FROM information_schema.tables WHERE table_type = 'VIEW' AND table_schema = 'public'
-- LOOP
-- EXECUTE 'GRANT ALL ON ' || quote_ident(r.table_schema) || '.' || quote_ident(r.table_name) || ' TO webuser';
--END LOOP;
END$$;
正如你所看到的,我有一些问题时,想'打印'的加薪通知功能。但我设法解决了谷歌。
根据以前的经验,我可以看出Postgres语法与CTE非常相似,我只需要在CTE之前添加一个递归,因此唯一真正的问题是我必须定义一些变量,为此我需要一个do块。
从这个结果我有一个简单的问题:
如何在do块中"执行"选择查询?我想在pgAdmin3的"数据输出"选项卡中查看结果。
我不想创造一个函数。
5条答案
按热度按时间pkmbmrz71#
DO
命令与PL/pgSQL函数DO
命令不返回行。您可以发送NOTICES
或RAISE
其他消息(使用默认的LANGUAGE plpgsql
),或者您可以写入(临时)表,然后从该表写入SELECT
以解决此问题。但实际上,可以使用create a function来定义返回类型,其中可以使用
RETURNS
clause和/或OUT
和INOUT
参数来定义返回类型,并以各种方式从函数返回。如果您不希望保存一个函数并使其对其他连接可见,请考虑使用"临时"函数,这是一个未记录但已建立良好的特性:
generate_series()
解决手头的问题对于当前的问题,您似乎不需要 * 任何 * 这样的查询,而是使用以下简单的查询:
为什么?
txu3uszq2#
这里有更多关于Erwin建议的临时表的解决方法的细节,这应该是问题的真正答案,因为这个问题更多的是针对"在开发过程中,我如何快速地编写一个带有select的代码块并查看结果",而不是解决这个实际的查询(从一开始的基本问题是"如何快速地开发/调试表值函数")。
尽管我必须说我想把generate_series部分的投票结果提高100倍;)
可以将结果选择到临时表中,
并从DO块外部的临时表中选择,
像这样:
这才是将查询快速转换为表值函数版本的基础,顺便说一句,如下所示:
顺便说一句,看看SQL-Server代码块来实现这一点:
变成这样:
(谢谢欧文!);)
7cjasjjr3#
要从
DO
匿名代码块获取记录,可以使用以下技术:通知
1.游标在事务范围中可见,因此应在一个事务中使用它。
1.游标变量的名称应与文本常量相同;
更多关于cursors的信息。技术源代码here(俄语)。
jm2pwxwz4#
这是一个不太离题(恕我直言),可能是有帮助的...
我最近遇到了这个问题,我需要在一个事务中执行许多语句,并返回一些(非常少的)数据,这些数据将向PHP脚本指示事务是如何处理的(受影响的记录和任何自定义错误代码)。
坚持RAISE NOTICE和RAISE [EXCEPTION]范例,我发现最好在返回的NOTICE/EXCEPTION中返回一个JSON字符串,这样,PHP应用程序只需要使用pg_last_notice()或pg_last_error()来获取和解码JSON字符串。
例如:
或
由于返回的JSON对象名为“std_response”,实际上是所有这些类型脚本的标准响应,因此编写单元测试非常容易,因为加载和执行SQL的 Package 器函数将始终返回一个“std_response”对象,该对象可以测试其值。
仅当在RAISE消息中返回微小的数据片段时,才应使用此范例(虽然我已经看到多达96,000个字符以这种方式返回-不确定限制是什么)。如果您需要返回更大的数据集,你需要将结果集保存到一个表中,但是至少你仍然可以使用这个范例来准确地分离出哪些记录属于被调用的SQL。将数据放入带有UUID的表中,并在NOTICE中返回UUID,如下所示:
它的好处是,由于它仍然是结构化的,并且描述了从哪个表中选择数据,因此它还可以用于应用程序中的单元测试。
(或者,您也可以使用Postgresql将结果集存储在memcache中,并让应用程序从那里拾取数据集,这样您就不必处理磁盘I/O,只是为了存储应用程序将用于生成一些HTML的结果集,然后在脚本完成时立即丢弃)
6ie5vjzr5#
正如公认的解决方案所指出的,do块实际上并不是为了生成行而设计的,然而,您在这里是因为您需要一种方法来执行某项操作并生成行,所以这里有一个示例函数,它使用args和变量作为一些引物来生成行。
表
tweets
| id(序列号)|发布标识(文本)|推特(文本)|
| - ------|- ------|- ------|
| 1个|美国广播公司|你好世界|
| 第二章|定义|导语|