Can I perform a
select dblink_exec ('merg',E'insert into table1(col1,col2) select * from dblink(\'mc\',\'select distinct col1, col2 from table2\') as t(col1 bigint, col2 text)');
to be able to insert a select from a different database on the same server ?
I also tried to execute the second part into a view and then select from the view but did not work
All you need is to connect to one of the databases then execute
CREATE EXTENSION dblink
then just use:
select dblink_exec('dbname=table1', ....)
Related
I have a Table named TEST with column name col1, col2, col3,col4..........
So, from information_schema.columns i will get details about this table object.
Now, i want to build a select query from TEST table by supplying colum name from information_schema.columns.
like this, select column_name from information_schema.columns where table_name = 'TEST'.This will return
column_name
col1
col2
col3
i want to use this output in select query from TEST. Like this
select col1, col2,col3,col4 from TEST.
Is this possible by single query?
You will have to compose an SQL string and execute that.
You can either do that with your client application or in a PostgreSQL function.
You must take special care to escape all string values using the format function or quote_ident and quote_literal to avoid problems from SQL injection.
I Have the following query
EXECUTE sp_MSForEachDB
'USE ?;
Select DB_NAME()AS DBName, count(DISTINCT TABLE.COLUMN) as "NEW_NAME"
FROM [dbo].[TABLE]'
Which gives me the results I want but for every database in my connection I get a separate output. Is there a way to put all these outputs from all the databases into one table. Sorry If I am not asking correctly sort of new to this...
if I understand you correctly this should work:
CREATE TABLE #Temp (DBName VARCHAR(250), NEW_NAME INT)
INSERT INTO #Temp
EXECUTE sp_MSForEachDB
'USE ?;
Select DB_NAME()AS DBName, count(DISTINCT TABLE.COLUMN) as "NEW_NAME"
FROM [dbo].[TABLE]'
SELECT * FROM #Temp
Below is an example of how this would work. I have modified the query so that it can be run on my machine as I don't have the table [dbo].[TABLE] in my databases:
Can anyone provide an example (with the various SQL statements involved) on how to use foreign data wrappers in postgresql to enable a table from a postgresql database A to be joined to a table from a postgresql database B?
It is unclear from the docs to what degree is the FDW functionality available in pgsql 9.0 versus 9.1. The docs also do not have any examples that shows how to join between 2 different postgresql databases (with WHERE qualifier push-down) using FDW.
http://www.postgresql.org/docs/9.0/static/sql-createforeigndatawrapper.html
http://www.postgresql.org/docs/9.1/static/ddl-foreign-data.html
http://www.depesz.com/index.php/2011/03/14/waiting-for-9-1-foreign-data-wrapper/
You manipulate it just like any table. Per Depesz' post:
CREATE FOREIGN TABLE passwd (
username text,
pass text,
uid int4,
gid int4,
gecos text,
home text,
shell text
) SERVER file_server
OPTIONS (format 'text', filename '/etc/passwd', delimiter ':', null '');
select * from passwd;
The docs have no examples of joining tables for a good reason: it's plain old SQL...
The join push-down currently is the subject of a GSOC:
http://wiki.postgresql.org/wiki/Enhancing_FDW_functionality_for_PostgreSQL_GSoC2011
http://nine-chapters.com/?p=5
The simplest solution I found is the dblink extension. I tested it on PostgreSQL 9.1:
create extension dblink.
select * from dblink('port=5452 host=localhost dbname=mydb user=myuser password=xxx',
'select id,spaltenname from variablen') as v (a int, b varchar(20));
http://www.postgresql.org/docs/9.1/static/dblink.html
A simple join would be:
with a as (select * from dblink('port=5452 host=localhost dbname=mydb user=myuser password=xxx', 'select id,spaltenname from variablen') as v (a int, b varchar(20)))
select a join (select 1)b on (true);
The example above enables you to join with a table on another postgresql server, but it is just a copy and then join. No automatic "WHERE qualifier push-down" as you called it. You could of course just select the lines WHERE you need them in the first statement...
If you want to join 2 different postgresql databases I recommend you to use dblink:
select datos.*
FROM dblink('hostaddr=192.168.0.10 port=5432 dbname=my_dbname user=my_user password=my_pass'::text, '
select field_1, field_2
from my_table order by field_1
'
::text)
datos(field_1, integer, field_2 character varying(10));
(I tested it on PostgreSQL 9.1.3)
http://www.postgresql.org/docs/9.2/static/contrib-dblink-function.html
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 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)