SQL expression for not changing the field in UPDATE? - sql

It must be a classic scenario, but I don't see any question for it...
I receive a lot of arguments in HTTP request for updating a row in the database.
Some other parameters are not set.
I am using some C++ framework for the SQL queries.
And I have a query like:
auto update(R"__(
UPDATE
table
SET
field1 = ?,
field2 = ?
WHERE
id = ?
)__");
exec_update(update, {field1.value_or(<?>), field2.value_or(<?>), id})
Because there can be around 30 fields to update, I don't want to create the query dynamically, but I would rather use some keyword to tell the Postgresql not to change the fields that I don't have new value for, how to achieve that?
Simply, what to put instead of the <?>?
I only found a similar question: How do I update selective fields in SQL (leaving some unchanged)?, which is a special case for this, I want to be able to set even NULL or whatever, I just want to not update some fields from the query without changing the query, I want to just have the values dynamic, not the query.
EDIT: I couldn't find anything better than having the dynamic query like:
auto update(fmt::format(
R"__(
UPDATE
table
SET
field1 = {},
field2 = {},
WHERE
id = {}
)__",
object.get_field1().has_value() ? fmt::format("'{}'", object.get_field1().value())
: "field1",
object.get_field2().has_value() ? fmt::format("'{}'", object.get_field2().value())
: "field2",
id));
, but I am not much satisfied with that.

Related

How to query a condition on a single object of sql record?

I'll try my best to explain the situation here. We are using Maria DB.
In certain case we are looping over all the records/rows of a REQUESTS table.
and for each object/record we are checking few conditions and if condition passes we are performing an action. All the said things here are being done using ruby. Say I want to check the same on pure SQL, I wanted to see how.
Sample Object a Request table:
[{"ot_rqst_id":27460354,"rqst_type_cd":"NONTP","svc_type_cd":"TD","sl_ttl_type_cd":"","lot_num":41843022, ttl_stg_cd: 'CMPLT'}]
What I want to check on sql:
To see if the ttl_stg_cd of this object is equal to 'CMPLT'. If it is then update it to NULL else "something_else".
Let me remind you again that, I am already doing this in ruby language, but I am not an expert on sql so help would be appreciated.
The following query should do what you want.
I have taken the id from your query string. You need to put in the real table name and check the WHERE clause. If you remove the WHERE clause it will update all records in the table, you may wish the change it to something like
WHERE column_X = value_Y
UPDATE table_name
SET ttl_stg_cd = CASE ttl_stg_cd
WHEN 'CMPLT' THEN null
ELSE 'something_else' END
WHERE ot_rqst_id = 27460354;

Dealing with multiple output results in UPSERT query [SQL]

I'm trying to do an update query in which a single row the table is updated and, if nothing has matched and updated, a new row is inserted. In each case, I need the query to return the ID of the inserted row.
The issue I'm having is this query is returning 2 separate results when the insert case is reached, one for each output (the first empty, the second containing the ID). I'm running this query using SQL Alchemy on python and I'm only able to see the first result, which is empty.
UPDATE [Rights]
SET accessLevel = :access_level
OUTPUT inserted.rightsID
WHERE principal = :principal and [function] = :function
IF ##ROWCOUNT = 0
INSERT INTO Rights(principal, [function], accessLevel)
OUTPUT inserted.rightsID
VALUES(:principal, :function, :access_level)
And I'm calling it like so:
inserted_right_id = session.execute(sql_rights_update, right).fetchall()
Can anyone recommend a way of changing the query so that I can still use the UPSERT method, but only receive one of the IDs? I was considering storing the OUTPUT values into a table and returning that, or wrapping the whole thing in a select but hopefully there's something more elegant out there.
Thanks a million.
Feeling quite dumb. I simply added a
IF EXISTS(SELECT * FROM Rights WHERE principal = :principal and [function] = :function)
UPDATE ...
ELSE
INSERT ...

Structuring many update statements in SQL Server

I'm using SQL Server. I'm also relatively new to writing SQL... in a strong way. It's mostly self-taught, so I'm probably missing key ideas in terms of proper format.
I've a table called 'SiteResources' and a table called 'ResourceKeys'. SiteResources has an integer that corresponds to the placement of a string ('siteid') and a 'resourceid' which is an integer id that corresponds to 'resourceid' in ResourceKeys. ResourceKeys also contains a string for each key it contains ('resourcemessage'). Basically, these two tables are responsible for representing how strings are stored and displayed on a web page.
The best way to consistently update these two tables, is what? Let's say I have 5000 rows in SiteResources and 1000 rows in ResourceKeys. I could have an excel sheet, or a small program, which generates 5000 singular update statements, like:
update SiteResources set resoruceid = 0
WHERE siteid IS NULL AND resourceid IN (select resourceid
from ResourceKeys where resourcemessage LIKE 'FooBar')
I could have thousands of those singular update statements, with FooBar representing each string in the database I might want to change at once, but isn't there a cleaner way to write such a massive number of update statements? From what I understand, I should be wrapping all of my statements in begin/end/go too, just in-case of failure - which leads me to believe there is a more systematic way of writing these update statements? Is my hunch correct? Or is the way I'm going about this correct / ideal? I could change the structure of my tables, I suppose, or the structure of how I store data - that might simplify things - but let's just say I can't do that, in this instance.
As far as I understand, you just need to update everything in table SiteResources with empty parameter 'placement of a string'. If so, here is the code:
UPDATE a
SET resourceid = 0
FROM SiteResources a
WHERE EXISTS (select * from ResourceKeys b where a.resourceid = b.resourceid)
AND a.siteid IS NULL
For some specific things like 'FooBar'-rows you can add it like this:
UPDATE a
SET resourceid = 0
FROM SiteResources a
WHERE EXISTS (select * from ResourceKeys b where a.resourceid = b.resourceid and b.resourcemessage IN ('FooBar', 'FooBar2', 'FooBar3', ...))
AND a.siteid IS NULL
Let me see if I understood the question correctly. You'd like to update resourceid to 0 if the resourcemessage corresponds to a list of strings ? If so, you can build your query like this.
UPDATE r
SET resourceid = 0
FROM SiteResources r
JOIN ResourceKeys k ON r.resourceid = k.resourceid
WHERE k.resourcemessage IN ('FooBar', ...)
AND r.siteid IS NULL;
This is using an extended UPDATE syntax in transact-sql allowing you to use a JOIN in the UPDATE statement. But maybe it's not exactly what you want ? Why do you use the LIKE operator in your query, without wildcard (%) ?
With table-valued parameters, you can pass a table from your client app to the SQL batch that your app submits for execution. You can use this to pass a list of all the strings you need to update to a single UPDATE that updates all rows at once.
That way you don't have to worry about all of your concerns: the number of updates, transactional atomicitty, error handling. As a bonus, performance will be improved.
I recommend that you do a bit of research what TVPs are and how they are used.

Update row with multiple columns

So I want to be able to update a row in my table. I know how to do this
UPDATE Param
SET(Param1=#Param1, Param2=#Param2, Param3=#Param3, ...)
WHERE ParamId = #ParamId
The problem is that I don't know which column will be updated and which isn't, it depends on what the user changed. And I have a lot of param to to check.
--idk if this will work, I am just trying to limit the amont of code posted
ISNULL(#Param1, Select Param1 from Param where WHERE ParamId = #ParamId)
I was thinking about dynamic SQL, but it poses to much of a security risk. Is there a way for me to do this faster? Or is there no way around this? If you need more info please ask.
You could use COALESCE/ISNULL but you don't need to select the old value as default as sub query, you can use it directly:
UPDATE Param
SET Param1=COALESCE(#Param1,Param1), Param2=COALESCE(#Param2,Param2), ...
WHERE ParamId = #ParamId
However,on this way you cannot set a nullable column to NULL. I assume this is desired.

Update A multi-valued field in Access

I have created a lookup table in Access to provide the possible values for a column. Now I need to update this column with the data it had before I converted the column. I am unable to figure out a SQL Query that will work. I keep getting the error "An UPDATE or DELETE query cannot contain a multi-valued field." My research has suggested that I just need to set the value of the column but this always updates 0 records:
UPDATE [table_name] SET [column_name].Value = 55 WHERE [table_name].ID = 16;
I know this query will work if I change it to update a text column, so it is definitely a problem with just this column.
If you're adding a value to your multi-valued field, use an append query.
INSERT INTO table_name( [column_name].Value )
VALUES (55)
WHERE ID = 16;
If you want to change one particular value which exists in your multi-valued field, use an UPDATE statement. For example, to change the 55 to 56 ...
UPDATE [table_name]
SET [column_name].Value = 56
WHERE [column_name].Value = 55 And ID = 16;
See Using multivalued fields in queries for more information.
I have figured this out! It certainly was counter-intuitive! You have to use an INSERT statement to do the update.
-- Update a record with a multi-valued field that has no value
INSERT INTO [table_name] ( [[column_name].[Value] )
VALUES(55)
WHERE [table_name].ID = 16;
This confused me because I was expecting an UPDATE statement. I think it actually inserts a record into a hidden table that is used to associate multiple values with this column.
I am working with Sharepoint, I created the tables as multi-value fields, ran into the error with my INSERT INTO statement, went back to Sharepoint to change to non-multi-value fields, but that didn't fix it.
Recreated the table without using multi-value fields, and the INSERT INTO worked just fine.
do not use the .value part
UPDATE [table_name] SET [column_name] = 55 WHERE [table_name].ID = 16;
INSERT INTO Quals (cTypes.[value])
SELECT Quals_ContractTypes.ContractType
FROM Quals_ContractTypes
WHERE (Quals.ID = Quals_ContractTypes.ID_Quals);
I gotta say I didn't understand very well your problem but I saw something strange in your query. Try this:
UPDATE [table_name] SET [column_name]= 55 WHERE [table_name].ID = 16;
UPDATE:
Look at this link: it has an example
UPDATE Issues
SET Issues.AssignedTo.Value = 10
WHERE (((Issues.AssignedTo.Value)=6)
AND ((Issues.ID)=8));
NOTES
You should always include a WHERE
clause that identifies only the
records that you want to update.
Otherwise, you will update records
that you did not intend to change. An
Update query that does not contain a
WHERE clause changes every row in the
table. You can specify one value to
change.
The Multi-Valued field refers to Access databases that have tables with columns, that allow you to select multiple values, like a Combo Checkbox list.
THOSE are the only Access types that SQL cannot work with. I've tested all Access lookup possibilities, including hard-coded values, and lookup tables. They work fine, but if you have a column that has the Allow Multiple select options, you're out of luck. Even using the INSERT INTO as mentioned below, will not work as you'll get a similar but different error, about INSERTing into multi-valued fields.
As mentioned it's best to avoid using such tables outside of Access, and refer to a table specifically for your external needs. Then write a macro/vba script to update the real tables with the data from the "auxiliary" table.