Postgres table alias for psql session - postgresql

I can alias a table name in a Postgres statement like this:
SELECT a.id FROM very_long_table_name AS a;
Is there a mechanism to set up a similar alias that persists for a psql session?
For example:
$: psql -d sample
sample=# CREATE ALIAS a for very_long_table_name;
sample=# select id from a limit 1;
id
____
1

As shown in the manual this can be done using psql variables:
sample=# \set a 'very_long_table_name'
sample=# select id from :a limit 1;
id
----
1
(1 row)
If you don't want to run \set every time manually, you can include your common short names in ~/.psqlrc which is read when you start psql

I don't know of a way to create such an alias, but you may create a view on top of your table, and give it a short name, e.g.
CREATE VIEW short_name AS
SELECT *
FROM very_long_table_name;
Then, use the view name as you would the alias. Since views generally perform as well as the underlying tables, with regard to indices, you should not lose much in terms of performance.

I think the best option is to create a temporary view.
This solution is not restricted to psql.
CREATE TABLE averylongname (id integer PRIMARY KEY);
INSERT INTO averylongname VALUES (1);
CREATE TEMPORARY VIEW x AS SELECT * FROM averylongname;
The view will automatically vanish when your database session ends, and it can be used with DML statements as well:
INSERT INTO x VALUES (2);
SELECT * FROM x;
id
----
1
2
(2 rows)

Related

postgres - select * from existing table - psql says table does not exist

Fresh postgres installation, db 'test', table 'Graeber' created from another program.
I want to see the content of table 'Graeber'. When I connect to the database and try to select the content of 'Graeber', the application tells me : ERROR: relation "graeber" does not exist.
See screenshot:
What is wrong here?
Try adding the schema as in:
select *
from public.Graeber
If that doesn't work, then it is because you have a capital letter so try:
select *
from public."Graeber"
Hope this helps.
When using the psql console in cmd, sometimes you may forget to add ';' at the end of select statement
Example -1: select * from user #does not give any result back
select * from user; #this works with ';' at the end
Don't take me wrong I faced this issue in Postgresql version 13
See This Example.
queuerecords=# create table employee(id int,name varchar(100));
CREATE TABLE
queuerecords=# insert into employee values(1,'UsmanYaqoob');
INSERT 0 1
queuerecords=# select * from employee;
id | name
----+-------------
1 | UsmanYaqoob
(1 row)

Postgresql: dblink in Stored Functions from local to remote database

I check below link which I used and running perfectly. But I want to opposite this things.
Postgresql: dblink in Stored Functions
My scenario: Two databases are there. I want to copy one table data from local to remote database. I used dblink for this used but I am confused how to use dblink to store the data?
Local database name: localdatabase
Remote Database name: remotedatabase
Can any one suggest me how can I do this?
Thanks in advance.
Something like the lines below should work:
SELECT dblink_connect('hostaddr=127.0.0.1 port=5432 dbname=mydb user=postgres password=mypasswd');
-- change the connection string to your taste
SELECT dblink_exec('INSERT INTO test (some_text) VALUES (''Text go here'');');
Where test is a table in the remote database with the following definition:
CREATE TABLE test(
id serial
, some_text text
);
After running dblink_exec(), you can check the results in the remote database (or locally, using dblink(), like in the example below).
SELECT * FROM dblink('SELECT id, some_text FROM test') AS d(id integer, some_text text);
id | some_text
----+--------------
1 | Text go here
(1 row)
You can wrap your dblink_exec call in a function as well:
CREATE OR REPLACE FUNCTION f_dblink_test_update(val text, id integer) RETURNS text AS
$body$
SELECT dblink_exec('UPDATE torles.test SET some_text=' || quote_literal($1) || ' WHERE id = ' || $2);
$body$
LANGUAGE sql;
As you can see, you can even build your query string dynamically. (Not that I advocate this approach, since you have to be careful not to introduce a SQL injection vulnerability into your system this way.)
Since dblink_exec returns with a text message about what it did, you have to define your function as RETURNS text unless there are other value-returning statements after the dblink_exec call.

How does view name get out of sync with view definition?

I tracked down a bug in my system to this anomaly - at least it's an anomaly in my system of 15 catalogs with similar but unequal schemas.
What causes the [TABLE_NAME] in [INFORMATION_SCHEMA].[VIEWS] to be different than the value in [VIEW_DEFINITION]?
It makes me think I don't understand something about Views or System Tables in SQL Server...
.
If you have renamed the view, the name changes, but the definition doesn't.
You should do this as a DROP/CREATE or an ALTER script, not by right-clicking or using sp_rename.
This is actually expected behavior for all modules. Here is a quick test using a simple stored procedure:
CREATE PROCEDURE dbo.proc_foo
AS
SELECT 1;
GO
-- rename it to proc_bar
EXEC sys.sp_rename N'dbo.proc_foo', N'proc_bar', N'OBJECT';
GO
-- check the definition from various sources
SELECT od = OBJECT_DEFINITION(OBJECT_ID(N'dbo.proc_bar')),
info_s = (SELECT ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_NAME = N'proc_bar' AND SCHEMA_NAME = N'dbo'),
sql_m = (SELECT definition FROM sys.sql_modules
WHERE [object_id] = OBJECT_ID(N'dbo.proc_bar'));
Results:
od info_s sql_m
----------------------------- ----------------------------- -----------------------------
CREATE PROCEDURE dbo.proc_foo CREATE PROCEDURE dbo.proc_foo CREATE PROCEDURE dbo.proc_foo
AS AS AS
SELECT 1; SELECT 1; SELECT 1;
In any case, you shouldn't be using INFORMATION_SCHEMA anyway...
The case against INFORMATION_SCHEMA views

postgresql: INSERT INTO ... (SELECT * ...) - II [duplicate]

I'm not sure if its standard SQL:
INSERT INTO tblA
(SELECT id, time
FROM tblB
WHERE time > 1000)
What I'm looking for is: what if tblA and tblB are in different DB Servers.
Does PostgreSql gives any utility or has any functionality that will help to use INSERT query with PGresult struct
I mean SELECT id, time FROM tblB ... will return a PGresult* on using PQexec. Is it possible to use this struct in another PQexec to execute an INSERT command.
EDIT:
If not possible then I would go for extracting the values from PQresult* and create a multiple INSERT statement syntax like:
INSERT INTO films (code, title, did, date_prod, kind) VALUES
('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy');
Is it possible to create a prepared statement out of this!! :(
As Henrik wrote you can use dblink to connect remote database and fetch result. For example:
psql dbtest
CREATE TABLE tblB (id serial, time integer);
INSERT INTO tblB (time) VALUES (5000), (2000);
psql postgres
CREATE TABLE tblA (id serial, time integer);
INSERT INTO tblA
SELECT id, time
FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB')
AS t(id integer, time integer)
WHERE time > 1000;
TABLE tblA;
id | time
----+------
1 | 5000
2 | 2000
(2 rows)
PostgreSQL has record pseudo-type (only for function's argument or result type), which allows you query data from another (unknown) table.
Edit:
You can make it as prepared statement if you want and it works as well:
PREPARE migrate_data (integer) AS
INSERT INTO tblA
SELECT id, time
FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB')
AS t(id integer, time integer)
WHERE time > $1;
EXECUTE migrate_data(1000);
-- DEALLOCATE migrate_data;
Edit (yeah, another):
I just saw your revised question (closed as duplicate, or just very similar to this).
If my understanding is correct (postgres has tbla and dbtest has tblb and you want remote insert with local select, not remote select with local insert as above):
psql dbtest
SELECT dblink_exec
(
'dbname=postgres',
'INSERT INTO tbla
SELECT id, time
FROM dblink
(
''dbname=dbtest'',
''SELECT id, time FROM tblb''
)
AS t(id integer, time integer)
WHERE time > 1000;'
);
I don't like that nested dblink, but AFAIK I can't reference to tblB in dblink_exec body. Use LIMIT to specify top 20 rows, but I think you need to sort them using ORDER BY clause first.
If you want insert into specify column:
INSERT INTO table (time)
(SELECT time FROM
dblink('dbname=dbtest', 'SELECT time FROM tblB') AS t(time integer)
WHERE time > 1000
);
This notation (first seen here) looks useful too:
insert into postagem (
resumopostagem,
textopostagem,
dtliberacaopostagem,
idmediaimgpostagem,
idcatolico,
idminisermao,
idtipopostagem
) select
resumominisermao,
textominisermao,
diaminisermao,
idmediaimgminisermao,
idcatolico ,
idminisermao,
1
from
minisermao
You can use dblink to create a view that is resolved in another database. This database may be on another server.
insert into TABLENAMEA (A,B,C,D)
select A::integer,B,C,D from TABLENAMEB
If you are looking for PERFORMANCE, give where condition inside the db link query.
Otherwise it fetch all data from the foreign table and apply the where condition.
INSERT INTO tblA (id,time)
SELECT id, time FROM dblink('dbname=dbname port=5432 host=10.10.90.190 user=postgresuser password=pass123',
'select id, time from tblB where time>'''||1000||'''')
AS t1(id integer, time integer)
I am going to SELECT Databasee_One(10.0.0.10) data from Database_Two (10.0.0.20)
Connect to 10.0.0.20 and create DBLink Extenstion:
CREATE EXTENSION dblink;
Test the connection for Database_One:
SELECT dblink_connect('host=10.0.0.10 user=postgres password=dummy dbname=DB_ONE');
Create foreign data wrapper and server for global authentication:
CREATE FOREIGN DATA WRAPPER postgres VALIDATOR postgresql_fdw_validator;
You can use this server object for cross database queries:
CREATE SERVER dbonepostgres FOREIGN DATA WRAPPER postgres OPTIONS (hostaddr '10.0.0.10', dbname 'DB_ONE');
Mapping of user and server:
CREATE USER MAPPING FOR postgres SERVER dbonepostgres OPTIONS (user 'postgres', password 'dummy');
Test dblink:
SELECT dblink_connect('dbonepostgres');
Import data from 10.0.0.10 into 10.0.0.20
INSERT INTO tableA
SELECT
column1,
,column2,
...
FROM dblink('dbonepostgres', 'SELECT column1, column2, ... from public.tableA')
AS data(column1 DATATYPE, column2 DATATYPE, ...)
;
Here's an alternate solution, without using dblink.
Suppose B represents the source database and A represents the target database:
Then,
Copy table from source DB to target DB:
pg_dump -t <source_table> <source_db> | psql <target_db>
Open psql prompt, connect to target_db, and use a simple insert:
psql
# \c <target_db>;
# INSERT INTO <target_table>(id, x, y) SELECT id, x, y FROM <source_table>;
At the end, delete the copy of source_table that you created in target_table.
# DROP TABLE <source_table>;

How to find table creation time?

How can I find the table creation time in PostgreSQL?
Example: If I created a file I can find the file creation time like that I want to know the table creation time.
I had a look through the pg_* tables, and I couldn't find any creation times in there. It's possible to locate the table files, but then on Linux you can't get file creation time. So I think the answer is that you can only find this information on Windows, using the following steps:
get the database id with select datname, datdba from pg_database;
get the table filenode id with select relname, relfilenode from pg_class;
find the table file and look up its creation time; I think the location should be something like <PostgreSQL folder>/main/base/<database id>/<table filenode id> (not sure what it is on Windows).
You can't - the information isn't recorded anywhere. Looking at the table files won't necessarily give you the right information - there are table operations that will create a new file for you, in which case the date would reset.
I don't think it's possible from within PostgreSQL, but you'll probably find it in the underlying table file's creation time.
Suggested here :
SELECT oid FROM pg_database WHERE datname = 'mydb';
Then (assuming the oid is 12345) :
ls -l $PGDATA/base/12345/PG_VERSION
This workaround assumes that PG_VERSION is the least likely to be modified after the creation.
NB : If PGDATA is not defined, check Where does PostgreSQL store the database?
Check data dir location
SHOW data_directory;
Check For Postgres relation file path :
SELECT pg_relation_filepath('table_name');
you will get the file path of your relation
check for creation time of this file <data-dir>/<relation-file-path>
I tried a different approach to get table creation date which could help for keeping track of dynamically created tables. Suppose you have a table inventory in your database where you manage to save the creation date of the tables.
CREATE TABLE inventory (id SERIAL, tablename CHARACTER VARYING (128), created_at DATE);
Then, when a table you want to keep track of is created it's added in your inventory.
CREATE TABLE temp_table_1 (id SERIAL); -- A dynamic table is created
INSERT INTO inventory VALUES (1, 'temp_table_1', '2020-10-07 10:00:00'); -- We add it into the inventory
Then you could get advantage of pg_tables to run something like this to get existing table creation dates:
SELECT pg_tables.tablename, inventory.created_at
FROM pg_tables
INNER JOIN inventory
ON pg_tables.tablename = inventory.tablename
/*
tablename | created_at
--------------+------------
temp_table_1 | 2020-10-07
*/
For my use-case it is ok because I work with a set of dynamic tables that I need to keep track of.
P.S: Replace inventory in the database with your table name.
I'm trying to follow a different way for obtain this.
Starting from this discussion my solution was:
DROP TABLE IF EXISTS t_create_history CASCADE;
CREATE TABLE t_create_history (
gid serial primary key,
object_type varchar(20),
schema_name varchar(50),
object_identity varchar(200),
creation_date timestamp without time zone
);
--delete event trigger before dropping function
DROP EVENT TRIGGER IF EXISTS t_create_history_trigger;
--create history function
DROP FUNCTION IF EXISTS public.t_create_history_func();
CREATE OR REPLACE FUNCTION t_create_history_func()
RETURNS event_trigger
LANGUAGE plpgsql
AS $$
DECLARE
obj record;
BEGIN
FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands () WHERE command_tag in ('SELECT INTO','CREATE TABLE','CREATE TABLE AS')
LOOP
INSERT INTO public.t_create_history (object_type, schema_name, object_identity, creation_date) SELECT obj.object_type, obj.schema_name, obj.object_identity, now();
END LOOP;
END;
$$;
--ALTER EVENT TRIGGER t_create_history_trigger DISABLE;
--DROP EVENT TRIGGER t_create_history_trigger;
CREATE EVENT TRIGGER t_create_history_trigger ON ddl_command_end
WHEN TAG IN ('SELECT INTO','CREATE TABLE','CREATE TABLE AS')
EXECUTE PROCEDURE t_create_history_func();
In this way you obtain a table that records all the creation tables.
--query
select pslo.stasubtype, pc.relname, pslo.statime
from pg_stat_last_operation pslo
join pg_class pc on(pc.relfilenode = pslo.objid)
and pslo.staactionname = 'CREATE'
Order By pslo.statime desc
will help to accomplish desired results
(tried it on greenplum)
You can get this from pg_stat_last_operation. Here is how to do it:
select * from pg_stat_last_operation where objid = 'table_name'::regclass order by statime;
This table stores following operations:
select distinct staactionname from pg_stat_last_operation;
staactionname
---------------
ALTER
ANALYZE
CREATE
PARTITION
PRIVILEGE
VACUUM
(6 rows)