I want to returns the number of rows affected by the last statement.
Using Microsoft SQL Server 2008 R2 I do it this way:
SELECT * FROM Test_table;
SELECT ##ROWCOUNT AS [Number Of Rows Affected];
Will gives:
Number Of Rows Affected
-----------------------
10
How about in PostgreSQL 9.3?
DO $$
DECLARE
total_rows integer;
BEGIN
UPDATE emp_salary
SET salary = salary+1;
IF NOT FOUND THEN
RAISE NOTICE 'No rows found';
ELSIF FOUND THEN
GET DIAGNOSTICS total_rows := ROW_COUNT;
-- the above line used to get row_count
RAISE NOTICE 'Rows Found : total_rows: %', total_rows;
END IF;
END $$;
AFAIK there is no such construct in postgresql however the number of rows is part of the result you get from postgresql.
CORRECTION: as a_horse_with_no_name states in his comment there is something similar which can be used within PL/pgSQL. Also see example in answer posted by
Achilles Ram Nakirekanti
From within programs however my original suggestion is in most cases easier then having to resort to the usage of PL/pgSQL.
When using libpq:
On the result of a select you can use PQntuples to determine the number of rows returned. For update, insert and delete you can use PQcmdTuples with the result to get the number of rows affected.
Other client libraries often have similar functionality.
For REF from referred article: GET DIAGNOSTICS integer_var = ROW_COUNT;
Related
I'm new to PostgreSql, used to work with SQL Server.
I'm having trouble understanding one scenario, quite simple from Sql Server perspective.
I need to have as the query result (e.g. dataset) the value of a variable.
I Sql Server i'd have something like this:
Declare #cnt int
Delete from MyTable
set #cnt = ##ROWCOUNT
select #cnt as FinalResult
The expected result was to use the value of the variable (e.g. #cnt as my resultset).
I tried the same in PostgreSql, using the follwoing code:
DO $$
DECLARE
affected_rows integer;
BEGIN
delete from mySchema.MyTable;
GET DIAGNOSTICS affected_rows := ROW_COUNT;
raise notice 'affected records: %', affected_rows;
select affected_rows as result;
END $$;
Obviously it throws me an error.
Could you please advise on how to approach it?
Many thanks.
I assume the error you get is "query has no destination for result data" which is caused by the select affected_rows as result; line. In Postgres' PL/pgSQL (and essentially every other procedural language in relational databases - except for T-SQL), the result of a query needs to be stored somewhere.
A do block is like a temporary function that does not return anything, so the only way to give feedback from there, is to use raise notice to print the number of deleted rows. You can't have a SELECT statement returning something from a DO block.
But you don't need PL/pgSQL for that to begin with:
with deleted as (
delete from table
returning *
)
select count(*) as final_result
from deleted;
How to execute query within format() function in Postgres? can any one please guide me.
IF NOT EXISTS ( SELECT format ('select id
from '||some_table||' where emp_id
='||QUOTE_LITERAL(m_emp_id)||' )
) ;
You may combine EXECUTE FORMAT and an IF condition using GET DIAGNOSTICS
Here's an example which you can reuse with minimal changes.I have passed table name using %I identifier and parameterised argument ($1) for employee_id. This is safe against SQL Injection.LIMIT 1 is used since we are interested if at least one row exists. This will improve query performance and is equivalent(or efficient) to using EXISTS for huge datasets with multiple matching rows.
DO $$
DECLARE
some_table TEXT := 'employees';
m_emp_id INT := 100;
cnt INT;
BEGIN
EXECUTE format ('select 1
from %I where employee_id
= $1 LIMIT 1',some_table ) USING m_emp_id ;
GET DIAGNOSTICS cnt = ROW_COUNT;
IF cnt > 0
THEN
RAISE NOTICE 'FOUND';
ELSE
RAISE NOTICE 'NOT FOUND';
END IF;
END
$$;
Result
NOTICE: FOUND
DO
The #Kaushik Nayak reply is correct - I will try just little bit more explain this issue.
PLpgSQL knows two types of queries to database:
static (embedded) SQL - SQL is written directly to plpgsql code. Static SQL can be parametrized (can use a varible), but the parameters should be used as table or column identifier. The semantic (and execution plan) should be same every time.
dynamic SQL - this style of queries is similar to classic client side SQL - SQL is written as string expression (that is evaluated) in running time, and result of this string expression is evaluated as SQL query. There are not limits for parametrization, but there is a risk of SQL injections (parameters must be sanitized against SQL injection (good examples are in #Kaushik Nayak reply)). More, there is a overhead with every time replanning - so dynamic SQL should be used only when it is necessary. Dynamic SQL is processed by EXECUTE command. The syntax of IF commands is:
IF expression THEN
statements; ...
END IF;
You cannot to place into expression PLpgSQL statements. So this task should be divided to more steps:
EXECUTE format(...) USING m_emp_id;
GET DIAGNOSTICS rc = ROW_COUNT;
IF cnt > 0 THEN
...
END IF;
I have million of rows in pg_largeobject_metadata table I want to delete. What I have tried so far is :
A simple select lo_unlink(oid) works fine
A perform lo_unlink(oid) in a loop of 10000 rows will also work fine
So when I delete recursively multiple rows i get this error. I cannot increase max_locks_per_transaction because it is managed by AWS.
ERROR: out of shared memory
HINT: You might need to increase max_locks_per_transaction.
CONTEXT: SQL statement "SELECT lo_unlink(c_row.oid)" PL/pgSQL function inline_code_block line 21 at
PERFORM SQL state: 53200
Here is the program I tried to write but I still get the Out of shared memory ERROR.
DO $proc$
DECLARE
v_fetch bigInt;
v_offset bigInt;
nbRows bigInt;
c_row record;
c_rows CURSOR(p_offset bigInt, p_fetch bigInt) FOR SELECT oid FROM pg_largeobject_metadata WHERE oid BETWEEN 1910001 AND 2900000 OFFSET p_offset ROWS FETCH NEXT p_fetch ROWS ONLY;
BEGIN
v_offset := 0;
v_fetch := 100;
select count(*) into nbRows FROM pg_largeobject_metadata WHERE oid BETWEEN 1910001 AND 2900000;
RAISE NOTICE 'End loop nbrows = %', nbRows;
LOOP -- Loop the different cursors
RAISE NOTICE 'offseter = %', v_offset;
OPEN c_rows(v_offset, v_fetch);
LOOP -- Loop through the cursor results
FETCH c_rows INTO c_row;
EXIT WHEN NOT FOUND;
perform lo_unlink(c_row.oid);
END LOOP;
CLOSE c_rows;
EXIT WHEN v_offset > nbRows;
v_offset := v_offset + v_fetch; -- The next 10000 rows
END LOOP;
END;
$proc$;
I am using Pg 9.5
Can anyone has faced this issue and could help please?
Each lo_unlink() grabs a lock on the object it deletes. These locks are freed only at the end of the transaction, and they are capped by max_locks_per_transaction * (max_connections + max_prepared_transactions) (see Lock Management). By default max_locks_per_transaction is 64, and cranking it up by several order of magnitudes is not a good solution.
The typical solution is to move the outer LOOP from your DO block into your client-side code, and commit the transaction at each iteration (so each transaction removes 10000 large objects and commits).
Starting with PostgreSQL version 11, a COMMIT inside the DO block would be possible, just like transaction control in procedures is possible.
I want to returns the number of rows affected by the last statement.
Using Microsoft SQL Server 2008 R2 I do it this way:
SELECT * FROM Test_table;
SELECT ##ROWCOUNT AS [Number Of Rows Affected];
Will gives:
Number Of Rows Affected
-----------------------
10
How about in PostgreSQL 9.3?
DO $$
DECLARE
total_rows integer;
BEGIN
UPDATE emp_salary
SET salary = salary+1;
IF NOT FOUND THEN
RAISE NOTICE 'No rows found';
ELSIF FOUND THEN
GET DIAGNOSTICS total_rows := ROW_COUNT;
-- the above line used to get row_count
RAISE NOTICE 'Rows Found : total_rows: %', total_rows;
END IF;
END $$;
AFAIK there is no such construct in postgresql however the number of rows is part of the result you get from postgresql.
CORRECTION: as a_horse_with_no_name states in his comment there is something similar which can be used within PL/pgSQL. Also see example in answer posted by
Achilles Ram Nakirekanti
From within programs however my original suggestion is in most cases easier then having to resort to the usage of PL/pgSQL.
When using libpq:
On the result of a select you can use PQntuples to determine the number of rows returned. For update, insert and delete you can use PQcmdTuples with the result to get the number of rows affected.
Other client libraries often have similar functionality.
For REF from referred article: GET DIAGNOSTICS integer_var = ROW_COUNT;
First of all, yes I've read documentation for DO statement :)
http://www.postgresql.org/docs/9.1/static/sql-do.html
So my question:
I need to execute some dynamic block of code that contains UPDATE statements and calculate the number of all affected rows. I'm using Ado.Net provider.
In Oracle the solution would have 4 steps:
add InputOutput parameter "N" to command
add BEGIN ... END; to command
add :N := :N + sql%rowcount after each statement.
It's done! We can read N parameter from command, after execute it.
How can I do it with PostgreSQL? I'm using npgsql provider but can migrate to devard if it helps.
DO statement blocks are good to execute dynamic SQL. They are no good to return values. Use a plpgsql function for that.
The key statement you need is:
GET DIAGNOSTICS integer_var = ROW_COUNT;
Details in the manual.
Example code:
CREATE OR REPLACE FUNCTION f_upd_some()
RETURNS integer AS
$func$
DECLARE
ct int;
i int;
BEGIN
EXECUTE 'UPDATE tbl1 ...'; -- something dynamic here
GET DIAGNOSTICS ct = ROW_COUNT; -- initialize with 1st count
UPDATE tbl2 ...; -- nothing dynamic here
GET DIAGNOSTICS i = ROW_COUNT;
ct := ct + i; -- add up
RETURN ct;
END
$func$ LANGUAGE plpgsql;
Call:
SELECT * FROM f_upd_some();
My solution is quite simple. In Oracle I need to use variables to calculate the sum of updated rows because command.ExecuteNonQuery() returns only the count of rows affected by the last UPDATE in the batch.
However, npgsql returns the sum of all rows updated by all UPDATE queries. So I only need to call command.ExecuteNonQuery() and get the result without any variables. Much easier than with Oracle.