Update all rows with one SQL query - sql

I'm using this PostgreSQL table to store configuration variables:
CREATE TABLE SYS_PARAM(
SETTING_KEY TEXT NOT NULL,
VALUE_TYPE TEXT,
VALUE TEXT
)
;
How I can update all configuration settings values using one SQL statement?

you can use where true at the end and it update all rows in your table.
for example:
UPDATE table_name set table_column = value where true;
it will be update all rows in one SQL query.

If you plan on performing these updates more than once or twice over time, it would be good to have a function handle this for you. You could use the table itself as a type for a variadic parameter within a function, like so:
-- The function
CREATE OR REPLACE FUNCTION update_sys_param(VARIADIC params sys_param[])
RETURNS VOID
AS $$
BEGIN
UPDATE sys_param
SET value_type = upd.value_type, value = upd.value
FROM
sys_param src
INNER JOIN
UNNEST(params) upd
ON (src.setting_key = upd.setting_key);
END; $$ LANGUAGE PLPGSQL;
-- To call it
SELECT update_sys_param(('SMTP_PORT','int','123'),('SMTP_OTHER','text','435343'));
However, if this is a one-time update you can try either of these two:
UPDATE using JOIN
UPDATE sys_param
SET
value_type = new.value_type,
value = new.value
FROM
sys_param src
INNER JOIN
new_params new --< this table/view/cte must already exist or you must create it.
ON (src.setting_key = new.setting_key);
UPDATE using CASE
UPDATE sys_param
SET value = CASE setting_key
WHEN 'SMTP_PORT' THEN '2100'
(..and so on..)
END;
-- You would need to repeat the case statement if you intend on updating the value_type, too.

I guess you can achieve this by doing correlated update.
Please refer to the posts below:
https://www.ibm.com/support/knowledgecenter/ssw_i5_54/sqlp/rbafyexsub4.htm

You can join against a list of values and update with that:
update sys_param
set value = v.new_value
from (
values
('SMTP_PORT', '123'),
('SMTP_SERVER', 'new_server'),
('SMTP_USERNAME', 'Arthur')
) as v(skey, new_value)
where v.skey = sys_param.setting_key;
This assumes that setting_key is the primary key of that table.

Related

How to store data from a SELECT statement and use that data to loop with an UPDATE statement

I am using PLSQL and I want to store the query results form SELECT statement in an array and then I want to loop using the elements from that array to UPDATE all the rows. The problem with the code below is that it returns a single-row. Sub-query returns more than one row because he is trying to set more than one variable in a row. Can you help me in this situation?
This is my code:
CREATE OR REPLACE PROCEDURE looping IS
BEGIN
FOR rec IN (SELECT IID FROM DATMCCN0)
LOOP
UPDATE DATMCCN0
SET E_NOME = (SELECT I_NOME FROM DAT_CCNCONFIG0 INNER JOIN DATMCCN0 ON DAT_CCNCONFIG0.I_NOME = DATMCCN0.CAPLIC where DATMCCN0.IID = rec.IID)
where IID = rec.IID;
END LOOP;
END;
EXECUTE looping;
You do not need a loop and can do it all in one MERGE statement (assuming your correlated query returns a single row for each IID):
CREATE OR REPLACE PROCEDURE looping
IS
BEGIN
MERGE INTO DATMCCN0 dst
USING (
SELECT b.IID,
I_NOME
FROM DAT_CCNCONFIG0 a
INNER JOIN DATMCCN0 b
ON a.I_NOME = b.CAPLIC
) src
ON ( src.IID = dst.IID)
WHEN MATCHED THEN
UPDATE SET E_NOME = src.I_NOME;
END;
If it does not then you will need to get only a single row, something like this:
CREATE OR REPLACE PROCEDURE looping
IS
BEGIN
MERGE INTO DATMCCN0 dst
USING (
SELECT b.IID,
MAX( I_NOME ) AS I_NOME
FROM DAT_CCNCONFIG0 a
INNER JOIN DATMCCN0 b
ON a.I_NOME = b.CAPLIC
GROUP BY b.IID
) src
ON ( src.IID = dst.IID)
WHEN MATCHED THEN
UPDATE SET E_NOME = src.I_NOME;
END;
One literal answer for your question "How to store data from a SELECT statement and use that data [to loop] with an UPDATE statement" would be a statement like this:
UPDATE
(SELECT src.E_NOME, dst.I_NOME
FROM DAT_CCNCONFIG0
JOIN DATMCCN0 src ON DAT_CCNCONFIG0.I_NOME = scr.CAPLIC
JOIN DATMCCN0 dst ON src.IID = dst.IID)
SET E_NOME = I_NOME;
However, it does not solve your problem that a single-row subquery returns more than one. Have a look at MT0's answer for that.

How to update all of the values of a table using merge into statement

How to update all the values from source table to destination table using merge into statement?
What I am trying to do is something like:
merge into src_table
using (select * from dest) dest_table
on (<some_condition>)
when matched then update set src_table.* = dest_table.*
where <condition>
I didn't find anything related to this on Google. I know one can achieve this using execute immediate style statement but I am looking for a better way.
you can do it with pl/sql
for src in ( select * from B ) loop
update A set ROW = src where A.id = src.id;
end loop;
or you can use alter table;
alter table your_table
rename to
your_new_table;

In SQL, How to add values after add a new column in the existing table?

I created a table and inserted 3 rows. Then I added a new column using alter. How can I add values to the column without using any null values?
Two solutions.
Provide a default value for the column. This value will be used initially for all existing rows. The exact syntax depends on your database, but will will usually look like ..
this:
ALTER TABLE YourTable
ADD YourNewColumn INT NOT NULL
DEFAULT 10
WITH VALUES;
Add the column with null values first. Then update all rows to enter the values you want.
Like so:
ALTER TABLE YourTable
ADD YourNewColumn INT NULL;
UPDATE YourTable SET YourNewColumn = 10; -- Or some more complex expression
Then, if you need to, alter the column to make it not null:
ALTER TABLE YourTable ALTER COLUMN YourNewColumn NOT NULL;
Why don't you use UPDATE statement:
UPDATE tablename SET column=value <WHERE ...>
WHERE is optional. For instance in T-SQL for table:
I can update column NewTestColumn by this statement:
UPDATE [dbo].[Table] SET [NewTestColumn] = 'Some value'
Suppose you have a Employee table with these columns Employee_ID, Emp_Name,Emp_Email initially. Later you decide to add Emp_Department column to this table. To enter values to this column, you can use the following query :
Update *Table_Name* set *NewlyAddedColumnName*=Value where *Columname(primary key column)*=value
Example update TblEmployee set Emp_Department='Marketing' where Emp_ID='101'
I think below SQL useful to you
update table_name set newly_added_column_name = value;
update table_name
set new_column=value
Update table_name set column_name = value where 'condition';
suppose emp is the table and Comm is the new column then fire the below query .
update emp set Comm=5000
For Microsoft SQL (T-SQL):
UPDATE TABLE_NAME SET COLUMN_NAME=10;
here 10 means it will set all values by default to 10

Is there a way to make a field only editable by a trigger?

In Sql Server 2008 is there a way to set a field that it can only be changed using a Trigger?
Example:
When you create a record it is set to NULL and then updated by a trigger to e.g 1.
It should not be able to be set to anything other than NULL by the user.
And then when it is updated the trigger will set the value to 2.
create table tmp (a int primary key, b int)
GO
create trigger tr_insupd_tmp on tmp
instead of insert, update
as
if not exists(select * from deleted)
-- Process Insert
insert into tmp
select a, 1
from inserted
else
-- Process Update
update tmp
set b = 2
from tmp t
inner join inserted i on t.a = i.a
GO
Have you considered using using computed columns. If you want data in this column to be only governed by database logic then computed columns are probably way to go.

IF UPDATE() in SQL server trigger

If there's:
IF UPDATE (col1)
...in the SQL server trigger on a table, does it return true only if col1 has been changed or been updated?
I have a regular update query like
UPDATE table-name
SET col1 = 'x',
col2 = 'y'
WHERE id = 999
Now what my concern is if the "col1" was 'x' previously then again we updated it to 'x'
would IF UPDATE ("col1") trigger return True or not?
I am facing this problem as my save query is generic for all columns, but when I add this condition it returns True even if it's not changed...So I am concerned what to do in this case if I want to add condition like that?
It returns true if a column was updated. An update means that the query has SET the value of the column. Whether the previous value was the same as the new value is largely irelevant.
UPDATE table SET col = col
it's an update.
UPDATE table SET col = 99
when the col already had value 99 also it's an update.
Within the trigger, you have access to two internal tables that may help. The 'inserted' table includes the new version of each affected row, The 'deleted' table includes the original version of each row. You can compare the values in these tables to see if your field value was actually changed.
Here's a quick way to scan the rows to see if ANY column changed before deciding to run the contents of a trigger. This can be useful for example when you want to write a history record, but you don't want to do it if nothing really changed.
We use this all the time in ETL importing processes where we may re-import data but if nothing really changed in the source file we don't want to create a new history record.
CREATE TRIGGER [dbo].[TR_my_table_create_history]
ON [dbo].[my_table] FOR UPDATE AS
BEGIN
--
-- Insert the old data row if any column data changed
--
INSERT INTO [my_table_history]
SELECT d.*
FROM deleted d
INNER JOIN inserted i ON i.[id] = d.[id]
--
-- Use INTERSECT to see if anything REALLY changed
--
WHERE NOT EXISTS( SELECT i.* INTERSECT SELECT d.* )
END
Note that this particular trigger assumes that your source table (the one triggering the trigger) and the history table have identical column layouts.
What you do is check for different values in the inserted and deleted tables rather than use updated() (Don't forget to account for nulls). Or you could stop doing unneeded updates.
Trigger:
CREATE TRIGGER boo ON status2 FOR UPDATE AS
IF UPDATE (id)
BEGIN
SELECT 'DETECT';
END;
Usage:
UPDATE status2 SET name = 'K' WHERE name= 'T' --no action
UPDATE status2 SET name = 'T' ,id= 8 WHERE name= 'K' --detect
To shortcut the "No actual update" case, you need also check at the beginning whether your query affected any rows at all:
set nocount on; -- this must be the first statement!
if not exists (select 1 from inserted) and not exists (select 1 from deleted)
return;
SET NOCOUNT ON;
declare #countTemp int
select #countTemp = Count (*) from (
select City,PostCode,Street,CountryId,Address1 from Deleted
union
select City,PostCode,Street,CountryId,Address1 from Inserted
) tempTable
IF ( #countTemp > 1 )
Begin
-- Your Code goes Here
End
-- if any of these "City,PostCode,Street,CountryId,Address1" got updated then trigger
-- will work in " IF ( #countTemp > 1 ) " Code)
This worked for me
DECLARE #LongDescDirty bit = 0
Declare #old varchar(4000) = (SELECT LongDescription from deleted)
Declare #new varchar(4000) = (SELECT LongDescription from inserted)
if (#old <> #new)
BEGIN
SET #LongDescDirty = 1
END
Update table
Set LongDescUpdated = #LongDescUpdated
.....