Can postgresql (specifically 9.6) stored procedures read/modify a separate database, or can they only operate on data within the local database where they are defined?
Postgres 9.6 does not have stored procedures, which were introduced with Postgres 11.
You probably mean Postgres functions, which have been there since time immemorial. It's a widespread misconception to call those "stored procedures".
Both are confined to the database in which they are executed - as Postgres will tell you if you try to prefix a database name to an object name:
ERROR: cross-database references are not implemented:
Unless you use the Foreign Data Wrapper infrastructure (you probably want the additional module postgres_fdw with that) or dblink, which allow exactly that after all ...
How to use (install) dblink in PostgreSQL?
Persistent inserts in a UDF even if the function aborts
How do I do large non-blocking updates in PostgreSQL?
Related
Aurora Postgres 11.9
In SQL Server we strictly follow the good programming practice that "every single call land on DB from the application will be a stored procedure instead of simple queries". In Oracle, we haven't experienced the same thing may be due to select stored procedures required additional cursors, and so on.
Can any expert Postgres person advise me what practice should we follow in progress in this regard and what are pros and cons in this case of Postgres?
In addition in SQL Server we use "rowversion" for data sync with BI and other external modules, is there any built-in alternate available in Postgres or should we have to do it with manual triggers?
Wondering if it is possible to create a dblink in postgresql that is not saved as an object in the db, but rather it is an in-memory object during the session of a function or running code? Then use it to connect and do queries.
New to postgresql and not sure how to search for this.
Any examples on how to do this?
I have a use case to distribute data across many databases on many servers, all in postgres tables.
From any given server/db, I may need to query another server/db.
The queries are quite basic, standard selects with where clauses on standard fields.
I have currently implemented postgres_FDW, (I'm, using postgres 9.5), but I think the queries are not using indexes on the remote db.
For this use case (a random node may query N other nodes), which is likely my best performance choice based on how each underlying engine actually executes?
The Postgres foreign data wrapper (postgres_FDW) is newer to
PostgreSQL so it tends to be the recommended method. While the
functionality in the dblink extension is similar to that in the
foreign data wrapper, the Postgres foreign data wrapper is more SQL
standard compliant and can provide improved performance over dblink
connections.
Read this article for more detailed info: Cross Database queryng
My solution was simple: I upgraded to Postgres 10, and it appears to push where clauses down to the remote server.
Say I have the following database hosts
core (host: a.b.c.d, dbaname: core, username: coreUser) with tables users, accounts and permissions
app1 (host: d.e.f.g, dbname: appdb1, username: appuser1)
app2 (host: h.i.k.l, dbname: appdb2, username: appuser2)
I would like core.users, core.accounts and core.permissions to be available as native tables on app1 and app2. I want to be able to mirror the exact table and inserts and updates on these tables should update the tables in the core. Is there a way to do this?
postgres_fdw can do the job.
The postgres_fdw module provides the foreign-data wrapper
postgres_fdw, which can be used to access data stored in external
PostgreSQL servers.
The functionality provided by this module overlaps substantially with
the functionality of the older dblink module. But postgres_fdw
provides more transparent and standards-compliant syntax for accessing
remote tables, and can give better performance in many cases.
FDW as you know stands for foreign data wrappers, it's used to connect external data sources to postgresql. In this case the external data source is another postgrsql database.
Yes, have a look at slony replication.
If you don't want to copy data then dblink extension might help you. It allows to call queries from one database to other. Combined with a function or a view could potentially be useful (although changes done to core would not be automatically reflected in "child" databases).
Postgres version: 9.3.4
I have the need to execute a function which resides in a remote database. The function returns a table of statistic data based on the parameters given.
I am in effect only mirroring the function in my local database to lock down access to this function using my database roles and grants.
I have found the following which seem to only provide table-based access.
http://www.postgresql.org/docs/9.3/static/postgres-fdw.html
http://multicorn.org/foreign-data-wrappers/#idsqlalchemy-foreign-data-wrapper
First question: is that correct or are there ways to use these libraries for non-table based operations?
I have found the following which seems to provide me with any SQL operation on the foreign database. The negative seems to be increased complexity and reduced performance due to manual connection and error handling.
http://www.postgresql.org/docs/9.3/static/dblink.html
Second question: are these assumptions correct, and are there any ways to bypass these concerns or libraries/samples one can begin from?
The fdw interface provides a way to make a library which can allow a postgresql database to query any external data source as though it was a table. From that point of view, it could do what you want.
The inbuilt postgresql_fdw driver, however, does not allow you to specify a function as a remote table.
You could write your own fdw driver, possibly using the multicorn library, or some other language. That is likely to be a bit of work though, and would have some specific disadvantages, in particular I don't know how you would pass parameters to the function.
dblink is probably going to be the easiest solution. It allows you to execute arbitrary SQL on the remote server, returning a set of records.
SELECT *
FROM dblink('dbname=mydb', 'SELECT * FROM thefunction(1,2,3)')
AS t1(col1 INTEGER, col2 INTEGER);
There are other potential solutions but they would all be more effort to set up.