Is there a way to define a named constant in a PostgreSQL query?
This question has been asked before (How do you use script variables in PostgreSQL?). However, there is a trick that I use for queries sometimes:
with const as (
select 1 as val
)
select . . .
from const cross join
That is, I define a CTE called const that has the constants defined there. I can then cross join this into my query, any number of times at any level. I have found this particularly useful when I'm dealing with dates, and need to handle date constants across many subqueries.
Is there a way to define a named constant/parameter in a single-statement SQL query?
You need to have dates
in the FROM
clause if you want it in the query. You can do this as:
WITH dates as (SELECT '2015-01-01' as start, '2016-01-01' as end)
SELECT t.*
FROM my_table t JOIN
dates d
ON t.start_date >= d.start AND t.end_date <= d.end;
Note: You can also do this with a CROSS JOIN
. I often write queries as:
WITH params as (
SELECT '2015-01-01' as start, '2016-01-01' as end
)
SELECT t.*
FROM params CROSS JOIN
my_table t
WHERE t.start_date >= params.start AND t.end_date <= params.end;
How to store a constant value in a Postgresql script
You can use psql
's \gset
to set a variable to the result of a query:
SELECT uuid_generate_v4() AS generated_id \gset
That will set the variable generated_id
.
To use the variable in your script, quote it like this:
:'generated_id'
Defining global constants in Postgresql stored function/procedures?
Take a look at this other answer. It uses the same approach that you do.
Create constant string for entire database
How to declare a variable in a PostgreSQL query
There is no such feature in PostgreSQL. You can do it only in pl/PgSQL (or other pl/*), but not in plain SQL.
An exception is WITH ()
query which can work as a variable, or even tuple
of variables. It allows you to return a table of temporary values.
WITH master_user AS (
SELECT
login,
registration_date
FROM users
WHERE ...
)
SELECT *
FROM users
WHERE master_login = (SELECT login
FROM master_user)
AND (SELECT registration_date
FROM master_user) > ...;
Declaring the table name in constant in Postgres Stored procedure
Well you can use dynamic SQL, but realize dynamic SQL often adds way more complexity. Good when really needed but should be avoided when possible. The following shows what would be needed for what you want to do. Is not having to type the table name for each SQL statement worth the additional trouble?
create or replace function get_data()
returns void as
$func$
declare
table_name_a constant text = 'asp.monitoring_bookmark_original';
file_cursor text = 'select distinct filename,systemuid from %i';
file_ref refcursor;
file_rec record;
data_cursor text =$stmt$select * from %i where filename = '%s' and systemuid= '%s' order by mindatetime, maxdatetime$stmt$;
data_ref refcursor;
data_rec record;
begin
--open the file cursor
open file_ref for execute format(file_cursor,table_name_a);
loop
fetch next from file_ref into file_rec;
exit when not found;
-- and extending from what the second query inplies
open data_ref for execute format(data_cursor,table_name_a,file_rec.filename,file_rec.systemid);
loop
fetch next from data_ref into data_rec;
exit when not found;
--//logic goes here
end loop;
end loop ;
end;
$func$
language plpgsql;
Create constant string for entire database
Create a tiny function that serves as "global constant":
CREATE OR REPLACE FUNCTION f_my_constant()
RETURNS text AS
$$SELECT text 'XXX'$$ LANGUAGE sql IMMUTABLE PARALLEL SAFE; -- see below
And use that function instead of 'BLABLABLA'
in your queries.
Be sure to declare the data type correctly and make the function IMMUTABLE
(because it is) for better performance with big queries.
In Postgres 9.6 or later add PARALLEL SAFE
, so it won't block parallel query plans. The setting isn't valid in older versions.
To change the constant, replace the function by running an updated CREATE OR REPLACE FUNCTION
statement. Invalidates query plans using it automatically, so queries are re-planned. Should be safe for concurrent use. Transactions starting after the change use the new function. But indexes involving the function have to be rebuilt manually.
Alternatively (especially in pg 9.2 or later), you could set a Customized Option as "global constant" for the whole cluster, a given DB, a given role etc, and retrieve the value with:
current_setting('constant.blabla')
One limitation: the value is always text
and may have to be cast to a target type.
Related:
- User defined variables in PostgreSQL
Many ways to set it:
- How does the search_path influence identifier resolution and the "current schema"
Related Topics
How to Create a Sequence in MySQL
SQL to Json - Array of Objects to Array of Values in SQL 2016
How to Dump the Data of Some Sqlite3 Tables
How to Do a Case Sensitive Search in Where Clause (I'M Using SQL Server)
What Is the Maximum Number of Columns in a Postgresql Select Query
MySQL: Invalid Use of Group Function
SQL Rank() Versus Row_Number()
SQL Server Equivalent of a Countif Aggregate Function
How to Get Difference Between Two Rows For a Column Field
Sql: If Clause Within Where Clause
Does the Order of Where Clauses Matter in Sql
T-SQL Datetime Rounded to Nearest Minute and Nearest Hours With Using Functions
Search Text in Stored Procedure in SQL Server