Pass table name used in FROM to function automatically?

前提是你 提交于 2019-12-13 04:10:08

问题


Working with PostgreSQL 9.6.3. I am new to functions in databases.

Let's say there are multiple tables of item numbers. Each one has the item number, the item cost and several other columns which are factored into the "additional cost". I would like to put the calculation into a function so I can call it for any of these tables.

So instead of:

SELECT 
    itemnumber, 
    itemname, 
    base, 
    CASE 
        WHEN labor < 100 AND overhead < .20 THEN
        WHEN .....
        WHEN .....
        WHEN .....
        .....
    END AS add_cost,
    gpm
FROM items1;

I can just do:

SELECT 
    itemnumber, 
    itemname, 
    base, 
    calc_add_cost(),
    gpm
FROM items1;

If I want to be able to use it on any of the item tables, I guess I would need to set a table_name parameter that the function takes since adding the table name into the function would be undesirable to say the least.

calc_add_cost(items1)

However, is there a simpler way such that when I call calc_add_cost() it will just use the table name from the FROM clause?

SELECT ....., calc_add_cost(item1) FROM item1

Just seems redundant.

I did come across a few topics with titles that sounded like they addressed what I was hoping to accomplish, but upon reviewing them it looked like they were a different issue.


回答1:


You can even emulate a "computed field" or "generated column" like you had in mind. Basics here:

  • Store common query as column?

Simple demo for one table:

CREATE OR REPLACE FUNCTION add_cost(items1)  -- function name = default col name
  RETURNS numeric AS
$func$
SELECT 
    CASE 
        WHEN $1.labor < 100 AND $1.overhead < .20 THEN numeric '1'
--      WHEN .....
--      WHEN .....
--      WHEN .....
        ELSE numeric '0'  -- ?
    END;
$func$
  LANGUAGE sql IMMUTABLE;

Call:

SELECT *, t.add_cost FROM items1 t;

Note the table-qualification in t.add_cost. I only demonstrate this syntax variant since you have been asking for it. My advise is to use the less confusing standard syntax:

SELECT *, add_cost(t) AS add_cost FROM items1 t;  -- column alias is also optional

However, SQL is a strictly typed language. If you define a particular row type as input parameter, it is bound to this particular row type. Passing various whole table types is more sophisticated, but still possible with polymorphic input type.

CREATE OR REPLACE FUNCTION add_cost(ANYELEMENT)  -- function name = default col name
  RETURNS numeric AS
$func$
SELECT 
    CASE 
        WHEN $1.labor < 100 AND $1.overhead < .20 THEN numeric '1'
--      WHEN .....
--      WHEN .....
--      WHEN .....
        ELSE numeric '0'  -- ?
    END;
$func$
  LANGUAGE sql IMMUTABLE;

Same call for any table that has the columns labor and overhead with matching data type.

dbfiddle here

Also see the related simple case passing simple values here:

  • How to put part of a SELECT statement into a Postgres function

For even more complex requirements - like also returning various row types - see:

  • Refactor a PL/pgSQL function to return the output of various SELECT queries


来源:https://stackoverflow.com/questions/46164931/pass-table-name-used-in-from-to-function-automatically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!