I would like to keep some computed columns in several tables and columns (PostgreSQL). The calculation is the same but there might be practically any number of tables and columns. So if the input is table1.field1 then the calculated field is table1.field1_calculated . And so forth. I was thinking on using triggers to maintain this, one trigger per field. This would require passing in the table and the field name as arguments into the function, assembling a SQL statement and executing it. I do not want to rely on plpgsql as that might not be available everywhere and everything I can find about dynamic SQL in PostgreSQL is a) old b) says you need plpgsql for that.
So
Is there a way in PostgreSQL 9.4+ or perhaps 9.5+ to create and execute dynamic SQL without plpgsql?
Is there a better way than triggering this function containing said dynamic SQL?
Ps. I am aware of the function/column notation trick but that doesn't really work here. For 2. I am suspecting rules might work but can't figure out how.
Related
I am trying to make use of Table declaration syntax and creating the same in Snowflake SQL.
I've gone through the snowflake community & documentations and all I could find is Table variable directly being assigned similar to SQL table variable or making use of a Table function.
generally Snowflake doesn't allow indexes nor type declarations.
other than that, you have two options:
use JS stored procedures, but they are not meant to return a range of values, all you can do is make a temporary table and put your set in there
use UDFs, that are (or well, can be) SQL and can return a table, but have a limited set of functionality
I am writing trigger for record updation in Postgresql using plpgsql . In trigger, I am accessing one value column value like below
NEW.mobileno -- This is usual way.
Now my requirement is , I will be having 'mobileno' text in one variable called dyn_columnname
Using this NEW and dyn_columnname , I should be access like NEW.mobileno value.
How can I achieve this..?
You need to use dynamic sql:
execute _dyn_sql_string into _dyn_col_value using _dyn_col_name;
http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN
It's usually better to avoid ending up with this situation to begin with, that being said, because the resulting query plans cannot be cached as efficiently as the plans from non-dynamic triggers.
If you're simply iterating through columns, consider approaching this by using dynamic sql, not to write a dynamic trigger function, but to write a dynamic function that creates or replaces a non-dynamic trigger function instead.
If you're using this because of some kind of business logic, consider revisitng your schema to aboid the situation entirely.
I have about 20 (and there will be more) specific stored procedures in my PostgreSQL 9.2 DB. They are used to make some calculations, some kind of financial "reports" (unfortunately, I can't just store data in tables and implement algorithms in the programs's code).
Procedures are very different one from another, they're operating on different tables, columns, implementing different algorithms etc.
Every procedure returns the same data type (numeric value).
And now, my client wants to create the funcionality, where user can select specific procedure (or combination of them, e.g. 10% of procedure's 1 returning value + 90% of procedure's 2 returning value), and use it as a "base" for later modeling.
He wants also my user to be able to change his selection later, without calling programmers every time. ;-)
I thought about making some tables:
Table: base_models
id <PK>,
user_id, <FK from users table>
model_name (varchar, or sth.)
Table: base_models_algorithms
base_model_id <FK from base_models>
algorithm_id <FK from algorithms>
percent_value (percent value of specific algorithm in model, eg. 10)
...and then, I need to store also my algorithm names (= stored procedures) in some table:
Table: algorithms
name: (stored procedure name, varchar?)
... and that's where the problem is.
Of course I can later create some view, with a column calculated by another procedure (model_current_value :-)), and decide what procedure to call depending on name stored in my algorithm's table, but that look awful for me. :(
There would be no data control (you can write anything to algorithms' table, and there is no way to ensure that this string is a name of procedure, returning correct data type etc.).
Of course I can fill the table myself, and won't let anyone to change it's data :-)
But maybe there is more elegant way to do the whole thing?
It sounds like you want the PL/PgSQL EXECUTE statement. You can use this to invoke dynamic SQL, eg for a 2-argument procedure with dynamic name:
EXECUTE format('SELECT %I($1,$2)', func_name) USING arg1, arg2;
This is a PL/PgSQL statement. It is not available in regular SQL. You can of course create a simple PL/PgSQL procedure that does this statement and call that from SQL.
I get the error "Incorrect syntax near the keyword 'truncate'." and not sure what's wrong with the syntax here, it's not obvious to me...probably something stupid but I need another set of eyes:
ALTER VIEW [dbo].[vw_All_Events]
AS
truncate table Event
Select [event_id]
,[site_id]
,[autogenerated]
,[creation_date]
,[last_update_date]
from Event
GO
A view only allows a single statement after the AS and it must be data retrieval (return a rowset). It can't be a different type including data definition, data modification, procedural, declarative, or any other.
You can do these things with a stored procedure, or a user-defined function (but can't do DDL & DML in a function).
In detail, a stored procedure allows flow-of-control statements like IF THEN ELSE BEGIN END WHILE RETURN. You can use DML to UPDATE, DELETE and INSERT. You can use DDL to CREATE and DROP tables and indexes, add columns and constraints, and so on. You can return multiple rowsets. You can execute dynamic SQL.
What are you trying to accomplish?
Better way, you use a stored procedure instead of view.
There are you write multiple statement and also get output.
You can only have select statements in views. Therefore, 'truncate' is an invalid command to use.
TRUNCATE does not work with views.
Check out this link
My company doing new policy because my company would have certification of some international standards. That policy is, the DBA not allowed to query directly into database, like :
select * from some_table, update some_table, etc.
We have to use stored procedure to do that queries.
Regarding my last question in here : Postgres pl/pgsql ERROR: column "column_name" does not exist
I'm wondering, do we have to create a stored procedure per table, or per condition?
Is there any way to create stored procedures more efficiently?
Thanks for your answer before..
and sorry for my bad english.. :D
Some reasons to use stored procedures are:
They have presumably undergone some testing to ensure that they do
not allow business rules to be broken, as well as some optimization
for performance.
They ensure consistency in results. Every time you are asked to
perform task X, you run the stored procedure associate with task X.
If you write the query, you may not write it the same way every time;
maybe one day you forget something silly like forcing text to the
same case before a comparison and something gets missed.
They start off taking somewhat longer to write than just a query, but
running that stored procedure takes less time than writing the query
again. Run it enough times and it becomes more efficient to have
written the stored procedure.
They reduce or eliminate the need to know the relationships of
underlying tables.
You can grant permissions to execute the stored procedures (with
security definer), but deny permissions on the underlying tables.
Programmers (if you separate DBAs and programmers) can be provided an
API, and that’s all they need to know. So long as you maintain the
API while changing the database, you can make any changes necessary
to the underlying relations without breaking their software; indeed,
you don’t even need to know what they have done with your API.
You will likely end up making one stored procedure per query you would otherwise execute.
I'm not sure why you consider this inefficient, or particularly time-consuming as compared to just writing the query. If all you are doing is putting the query inside of a stored procedure, the extra work should be minimal.
CREATE OR REPLACE FUNCTION aSchema.aProcedure (
IN var1 text,
IN var2 text,
OUT col1 text,
OUT col2 text
)
RETURNS setof record
LANGUAGE plpgsql
VOLATILE
CALLED ON NULL INPUT
SECURITY DEFINER
SET search_path = aSchema, pg_temp
AS $body$
BEGIN
RETURN QUERY /*the query you would have written anyway*/;
END;
$body$;
GRANT EXECUTE ON FUNCTION aSchema.aProcedure(text, text) TO public;
As you used in your previous question, the function can be even more dynamic by passing columns/tables as parameters and using EXECUTE (though this increases how much the person executing the function needs to know about how the function works, so I try to avoid it).
If the "less efficient" is coming from additional logic that is included in the function, then the comparison to just using queries isn't fair, as the function is doing additional work.