Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.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
Sql 如何将参数传递到日期函数中_Sql_Postgresql_Parameter Passing_Plpgsql_Date Arithmetic - Fatal编程技术网

Sql 如何将参数传递到日期函数中

Sql 如何将参数传递到日期函数中,sql,postgresql,parameter-passing,plpgsql,date-arithmetic,Sql,Postgresql,Parameter Passing,Plpgsql,Date Arithmetic,我试图创建一个简单的函数,但似乎无法将参数传入日期函数。 以下是函数: CREATE OR REPLACE FUNCTION test(source int,days text) RETURNS integer AS $totals$ declare totals integer; BEGIN select count(id) into totals from ad where createdate::date = dat

我试图创建一个简单的函数,但似乎无法将参数传入日期函数。
以下是函数:

CREATE OR REPLACE FUNCTION test(source int,days text)
RETURNS integer AS $totals$
declare
    totals integer;
BEGIN

   select 
           count(id) into totals
     from  ad
    where
       createdate::date = date(current_date - interval '$2' day) and
       source = $1;

   RETURN totals;

END;
$totals$ LANGUAGE plpgsql;

这是无效语法:
interval'$2'day
。在运行SQL之前,不仅要将变量交换到位,还需要将正确的值传递给函数

您可能想将字符串
'day'
连接到字符串(
text
)变量
$2
,也称为
days
(不是字面字符串
'2'
)。所以
$2 | |天“
天| |天”

因为这不是一个单独的文本,所以您需要一个显式强制转换,而不仅仅是一个类型标签,所以类似于
cast($2 | |“day”作为interval)
(days | |“day”)::interval

已经揭示了您的语法错误。但是,这可以通过多种方式变得更简单、更快和更干净

CREATE OR REPLACE FUNCTION test(_source int, _days int)
  RETURNS integer AS
$func$
SELECT count(*)::int
FROM   ad a
WHERE  a.source = $1
AND    a.createdate::date = current_date - $2
$func$  LANGUAGE sql STABLE;
  • 首先,要从
    日期中减去天数,您可以减去
    整数。因此,我在这里使用一个
    integer
    参数

  • 对于这样一个简单的函数,您不需要plpgsql。改用SQL函数——它可以在更大的查询上下文中“内联”,因此在某些情况下可以更好地优化

  • 该功能可以是稳定的:

  • 您的函数中内置了命名冲突
    source
    显然也是一个列名。尽量避免这样。通常的做法是在变量和参数前面加下划线(除此之外没有特殊含义)。您还可以使用函数名(或使用位置参数)对列名和/或前置参数名进行表限定,使其明确无误。我在这里都做了

  • 假设
    id
    是您的PK列,因此定义了
    notnull
    count(*)
    count(id)
    做的相同,稍微短一点,也便宜一点。我强制转换为
    integer
    ,因为count()将返回一个
    bigint

然而,我怀疑您命名不准确的列
createdate
实际上不是
日期
,而是
时间戳
(问题中缺少基本表定义)。在这种情况下,以不同的方式表达查询更有效:

CREATE OR REPLACE FUNCTION test(_source int, _days int)
  RETURNS integer AS
$func$
SELECT count(*)::int
FROM   ad a
WHERE  a.source = $1
AND    a.createdate >= now() - interval '1 day' * $2
AND    a.createdate <  now() - interval '1 day' * ($2 - 1)
$func$ LANGUAGE sql STABLE;
创建或替换功能测试(\u source int,\u days int)
将整数返回为
$func$
选择计数(*)::int
从公元前
其中a.source=$1
和a.createdate>=now()-间隔“1天”*$2
和a.createdate
  • 此表达式更简单,因此更有效。它还可以在
    (createdate)
    上使用普通的索引,或者在
    (source,createdate)
    上使用更好的索引,这对于大型表很重要

  • 还演示了另一种减去天数的方法。您可以乘以
    间隔“1天”
    。相关的:


谢谢您的回复。我试过:date=date(当前日期-(days | |'day')::interval)但它不起作用。这是否如您所料?@user1609817请澄清“不起作用”。您是否收到错误消息?如果收到,是什么消息?它做了“错误”的事情吗?如果是,它做了什么?你希望它做什么?我很抱歉。我在测试一个不同的函数。你的解决方案有效!!非常感谢。您的Postgres版本、表定义和收到的错误消息将是重要的详细信息。是的,这里的答案有效。我在测试一个旧版本的函数。。。谢谢你的深入回答。谢谢你的这个欧文!