Common Table Expression in PostgreSQL - postgresql

I am just learning the CTE and I want to create the dynamic query inside the WITH clause.
Below is what i have written code.
WITH name1 AS (
SELECT schema_name as my_schema
FROM public.schema_table
), name2 AS (
SELECT num_rows as my_row
FROM my_schema.row_table
)
SELECT my_row
from name2;
From the first query inside the WITH give number of schema exist in one database and that schema name return by
SELECT schema_name as my_schema
FROM public.schema_table
I want to use in second query as I am saving it to my_schema.
but when i run this query then it gives me error like my_schema not exists that correct because I want to use the value my_schema contains.
How can you do that?

Firstly, you do not appear to have used name1 anywhere in your query, so I suspect you may not have understood WITH fully.
However it looks like you might have multiple tables called row_table each living in it's own schema and want to create a query that will let you choose which schema to fetch from.
FROM my_schema.row_table
^^^^^^^^^
my_schema is not a variable, it is the name of the schema. To do what you want you are going to have to use the pg_catalog tables to find the oid for the relation within the schema that you need and look up the information that way.
An alternative solution could be to manipulate the search path to do your bidding:
BEGIN;
SET LOCAL SCHEMA 'my_schema';
SELECT num_rows FROM row_table; -- will use my_schema.
COMMIT;

Related

Find a table in a schema without knowing in advance

Is it possible to easily see what tables exist in what schemas, at a glance?
So far I have had to connect to a database, view the schemas, then change the search path to one of the schemas and then list the tables. I had to do this for multiple schemas until I found the table I was looking for.
What if there is a scenario where you inherit a poorly documented database and you want to find a specific table in hundreds of schemas?
Ideally I imagine some output like so;
SCHEMA TABLE
--------------------
schema1 table1
schema2 table2
schema2 table1
--------------------
Or even the more standard <SCHEMA_NAME>.<TABLE_NAME>;
schema1.table1
schema2.table2
schema2.table1
The latter output would be even better since you could simply check the table using copy-paste;
my-database=# \d schema2.table1
Ideally I'm hoping I missed a built-in command to find this. I don't really want to create and memorize a lengthy SQL command to get this (somewhat basic) information.
You can make use of pg_tables
SELECT schemaname, tablename,
quote_ident(schemaname) || '.' || quote_ident(tablename)
FROM pg_tables
WHERE tablename = 'test';

Postgresql search_path issue

Based on past experience and documentation related to search_path:
"The first matching table in the search path is taken to be the one wanted. If there is no match in the search path, an error is reported, even if matching table names exist in other schemas in the database."
But when I run this:
financialdw=> show search_path;
search_path
------------------------------------------------------
"$user, prismdms, prism_nonrestrict, prism_restrict"
(1 row)
financialdw=> select count(*) from addr;
ERROR: relation "addr" does not exist
LINE 1: select count(*) from addr;
^
financialdw=> select count(*) from prismdms.addr;
count
-------
24428
(1 row)
prismdms is in my search_path and I have the necessary permissions on all tables within it. Shouldn't I be able, as the document states, query the table without the schema name qualifying it?
Your search_path has a single schema in it, and that single schema has the long and unlikely name of $user, prismdms, prism_nonrestrict, prism_restrict.
The double quotes should just be around $user, not the entire thing.

How to write a select statement for a table in postgres that is inside a schema?

I have a postgres DB and inside of it there are many schemas.
Each one of those schemas contains tables. For example:
Schema Name: personal has tables actions_takes, page_views etc
How can i write a SQL query or ActiveRecord query to query the table inside the schema?
Something like:
select * from actions_takes where user_id = 123;
I can create a model for each table and query it that way, but i want to write a script that passed a user goes over all tables and get the data for that user.
in pgAdmin 4 web console should use double quotation marks like following select statement
SELECT "col1", "col2"
FROM "schemaName".profile;
Point to specific table within a given schema using a dot notation schema.table_name. In your case it translates to
select * from personal.actions_takes where user_id = 123;
For me this query worked : select * from schemaName."Table_Name"

Postgresql: cannot get result using sub-query at FROM ... place

What I'm trying to accomplish is to get aggregated data for all unique combinations of sendercompid, targetcompid, msgtype through all tables in inner SQL.
I expect to have from 20mil to 40mil unique rows in resulting output.
I cannot succeed in running next query on Postgresql 8.3.13:
SELECT
sendercompid, targetcompid, count(msgtype), msgtype
FROM
(SELECT table_name
FROM information_schema.tables
WHERE table_catalog = 'test'
AND table_schema = 'msg'
AND (table_name like 'fix_aee_20121214%') OR
(table_name like 'fix_aee2_20121214%')
)
WHERE
(sendercompid LIKE '%201%') OR
(targetcompid LIKE '%201%')
GROUP BY
sendercompid, targetcompid, msgtype ;
If this select is being split on 2 : outer and inner, then :
inner will provide list of tables and outer will do select and grouping from each table .
If I run those two SQLs as one, I have an alias error from pgsql db
ERROR: subquery in FROM must have an alias
I tried use alias, but this error not disappear.
Any thoughts what I am missing there?
Thank you.
FROM doesn't work the way you think it does. A sub-select works like any other query: it produces a set of rows. The outer SELECT works with those rows as though they were a table. There's no special magic beyond that; it has no idea that the values you're returning are table names, and won't treat them as such.
You can probably accomplish what you want using the catalog tables, but that would be complicated and hack-y.
Since your sub-tables appear to be date-based partitions, I think what you really want to use is the partitioning support built into Postgres, described in these docs. Essentially your partitions inherit from a parent table, and you set up range constraints on each child. When you query from the parent table with constraint_exclusion enabled, Postgres automatically selects the appropriate partition.
You can "run" such query using dynamic SQL. The idea - to form the proper query with table name as string inside PL\pgSQL procedure and EXECUTE it. Something like:
CREATE OR REPLACE FUNCTION public.function1 (
)
RETURNS TABLE (
"field1" NUMERIC,
"field2" NUMERIC,
...
) AS
$body$
BEGIN
RETURN EXECUTE 'SELECT * FROM '|| (SELECT table_name from information_schema.tables
where table_catalog = 'test' AND
table_schema='msg' AND
(table_name like 'fix_aee_20121214%') OR
(table_name like 'fix_aee2_20121214%'));
END;
$body$
LANGUAGE 'plpgsql';
Then use something like:
SELECT sendercompid, targetcompid, count(msgtype), msgtype
FROM function1
WHERE (sendercompid LIKE '%201%') OR
(targetcompid LIKE '%201%')
GROUP BY sendercompid, targetcompid, msgtype ;
Or you can create function with full query and some parameters to build WHERE clause.
Details: EXECUTE,
If this is just a concept then:
ERROR: subquery in FROM must have an alias.
There's is no information where columns sendercompid, targetcompid, count(msgtype), msgtype are come from.
SELECT sendercompid, targetcompid, count(msgtype), msgtype from (
SELECT table_name from information_schema.tables
where table_catalog = 'test' AND
table_schema='msg' AND
(table_name like 'fix_aee_20121214%') OR
(table_name like 'fix_aee2_20121214%')
) a
WHERE (sendercompid LIKE '%201%') OR
(targetcompid LIKE '%201%')
GROUP BY sendercompid, targetcompid, msgtype ;
Use alias for subquery. Better you alias for all tables to avoid confusion.

SELECT .. INTO to create a table in PL/pgSQL

I want to use SELECT INTO to make a temporary table in one of my functions. SELECT INTO works in SQL but not PL/pgSQL.
This statement creates a table called mytable (If orig_table exists as a relation):
SELECT *
INTO TEMP TABLE mytable
FROM orig_table;
But put this function into PostgreSQL, and you get the error: ERROR: "temp" is not a known variable
CREATE OR REPLACE FUNCTION whatever()
RETURNS void AS $$
BEGIN
SELECT *
INTO TEMP TABLE mytable
FROM orig_table;
END; $$ LANGUAGE plpgsql;
I can SELECT INTO a variable of type record within PL/pgSQL, but then I have to define the structure when getting data out of that record. SELECT INTO is really simple - automatically creating a table of the same structure of the SELECT query. Does anyone have any explanation for why this doesn't work inside a function?
It seems like SELECT INTO works differently in PL/pgSQL, because you can select into the variables you've declared. I don't want to declare my temporary table structure, though. I wish it would just create the structure automatically like it does in SQL.
Try
CREATE TEMP TABLE mytable AS
SELECT *
FROM orig_table;
Per http://www.postgresql.org/docs/current/static/sql-selectinto.html
CREATE TABLE AS is functionally similar to SELECT INTO. CREATE TABLE AS is the recommended syntax, since this form of SELECT INTO is not available in ECPG or PL/pgSQL, because they interpret the INTO clause differently. Furthermore, CREATE TABLE AS offers a superset of the functionality provided by SELECT INTO.