Update statement clarification - sql

I'm extremely new to "updating" databases as I've only ever wrote queries as select statements.
I have a record i need to delete or change from the database. How would I go about doing that? Lets take updating a column first.
I want to update the "Customer" table and the "SNumber" column where the "TicketNum" Column is "123" Right now "SNumber" for that record is blank, and i'd like it to be "115"
I was thinking:
update Customer
set snumber = '115'
where ticketnum = '123'
Obviously I do not want to run this query with fear of messing up the database.
The second part of this is how would I delete the record all together?
Thanks

that is correct.
remember you can update and then issue a ROLLBACk if you need to undo it.
delete is similar:
delete customer where ticketnum = 123;

If you are new I recommend searching about CRUD operations using tSQL. For example:
Update on MSDN
Delete on MSDN
As for your question. You will not mess up the database with that UPDATE clause, it is correct.
To delete the row just use:
DELETE FROM Customer
WHERE ticketnum = '123'
ROLLBACK, as recommended on other answer, helps to roll back an action (transaction) that was incorrect or erroneus or just because some data is not correct. See MSDN for ROLLBACK sintax
This is closely related to TRANSACTIONS concept.

The general form of update in SQL is
UPDATE table
SET column = expression
WHERE predicates;
and an example would be
UPDATE suppliers
SET description = 'gorilla glass', product = 'screens'
WHERE name = 'corning';
As other posters have noted, your SQL update is correct.

Related

SQL update multiple rows with different values where they match a value from a list

So perhaps the title is a little confusing. If you can suggest better wording for that please let me know and i'll update.
Here's the issue. I've got a table with many thousands of rows and i need to update a few thousand of those many to store latest email data.
For example:
OldEmail#1.com => NewEmail#1.com
OldEmail#2.com => NewEmail#2.com
I've got a list of old emails ('OldEmail#1.com','OldEmail#2.com') and a list of the new ('NewEmail#1.com','NewEmail#2.com'). The HOPE was was to sort of do it simply with something like
UPDATE Table
SET Email = ('NewEmail#1.com','NewEmail#2.com')
WHERE Email = ('OldEmail#1.com','OldEmail#2.com')
I hope that makes sense. Any questions just ask. Thanks!
You could use a case expression:
update mytable
set email = case email
when 'OldEmail#1.com' then 'NewEmail#1.com'
when 'OldEmail#2.com' then 'NewEmail#2.com'
end
where email in ('OldEmail#1.com','OldEmail#2.com')
Or better yet, if you have a large list of values, you might create a table to store them (like myref(old_email, new_email)) and join it in your update query, like so:
update t
set t.email = r.new_email
from mytable t
inner join myref r on r.old_email = t.email
The actual syntax for update/join does vary accross databases - the above SQL Server syntax.
With accuracy to the syntax in particular DBMS:
WITH cte AS (SELECT 'NewEmail#1.com' newvalue, 'OldEmail#1.com' oldvalue
UNION ALL
SELECT 'NewEmail#2.com', 'OldEmail#2.com')
UPDATE table
SET table.email = cte.newvalue
FROM cte
WHERE table.email = cte.oldvalue
or, if CTE is not available,
UPDATE table
SET table.email = cte.newvalue
FROM (SELECT 'NewEmail#1.com' newvalue, 'OldEmail#1.com' oldvalue
UNION ALL
SELECT 'NewEmail#2.com', 'OldEmail#2.com') cte
WHERE table.email = cte.oldvalue
Consider prepared statement for rows update in large batches.
Basically it works as following :
database complies a query pattern you provide the first time, keep the compiled result for current connection (depends on implementation).
then you updates all the rows, by sending shortened label of the prepared function with different parameters in SQL syntax, instead of sending entire UPDATE statement several times for several updates
the database parse the shortened label of the prepared function , which is linked to the pre-compiled result, then perform the updates.
next time when you perform row updates, the database may still use the pre-compiled result and quickly complete the operations (so the first step above can be skipped).
Here is PostgreSQL example of prepare statement, many of SQL databases (e.g. MariaDB,MySQL, Oracle) also support it.

Cannot use OUTPUT clause with INTO clause when using Triggers to update records in SQL, when adding a record in FileMaker

I know a similar question to this has been asked a fair few times on here, but none seem to give me the answer I need - specifically because I am talking about the relationship between SQL and FileMaker.
See, I'm not actually using an OUTPUT clause at all in my Trigger! But FileMaker seems to either think I am, or insert something itself as an OUTPUT clause that I can't see.
Here is an example trigger:
CREATE TRIGGER [dbo].[TRG_person__name]
ON [dbo].[person]
AFTER INSERT,UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF UPDATE ( person_name_first )
BEGIN
UPDATE person
SET person_name_first = dbo.mslTitleCase ( i.person_name_first )
FROM person AS x
JOIN inserted AS i ON x._pk_person = i._pk_person
WHERE x._pk_person = i._pk_person
END
--END IF
END
The mslTitleCase function has been declared and works, if I was to create a record using a SQL Query.
But I can an error when creating a new record in FileMaker.
Does anyone have any tips to find a way to stop this error in FileMaker?
Any guidance greatly appreciated.
Thank you
Lewis
This has been reported as a bug: http://help.filemaker.com/app/answers/detail/a_id/7870/~/external-sql-data-sources-(ess)%3A-unable-to-write-to-a-table-with-triggers-on
It does not look like it was resolved.
You may have other problems, but the correct syntax for the update is:
UPDATE p
SET person_name_first = dbo.mslTitleCase ( i.person_name_first )
FROM person p JOIN
inserted i
ON p._pk_person = i._pk_person
WHERE p._pk_person = i._pk_person;
The important change is that the update references the table alias not the table name. I think p is a much better alias than x for a table named person.
It sounds like your application is using the OUTPUT clause to directly return the modified data. If the table has any trigger, this is not allowed. They would have to output the modified data into a table, and then select the data from the table.
The issue is covered in this article:
https://blogs.msdn.microsoft.com/sqlprogrammability/2008/07/11/update-with-output-clause-triggers-and-sqlmoreresults/
If this is the case, you will not be able to add a trigger to the table. The corrections to the data will need to happen from an external source.

Access 2010 SQL - UPDATE query not working

I need to create a query for updating a column in a table with values taken from another table and matching a field.
These are the 2 tables:
tblMain
ID Autonumbering
Key Text
Stat1 Integer
tblStat1
ID Autonumbering
Key Text
Freq Integer
I want to UPDATE the tblMain.Stat1 column with tblStat1.Freq value on each record in which tblMain.Key = tblStat1.Key.
I tried this syntax (found somewhere as an example)
UPDATE tblMain
SET tblMain.Stat1 = tblStat1.Freq
WHERE tblMain.Key = tblStat1.Key;
This doesn't work and returns an error on the 2nd row.
After some trials I found that the correct syntax (built with the Access query generator) is this:
UPDATE (tblMaibn INNER JOIN tblStat1 ON tblMain.Key = tblStat1.Key)
SET tblMain.Stat1 = tblStat1.Freq;
In this 2nd syntax, there is no trace of the WHERE condition.
Can someone help me to understand what's wrong with the 1st syntax.
Since I'm building a new table (the join), how can it work on tblMain?
As I said, I found the wrong syntax as an example of UPDATE statement.
Thank you in advance.
Bye,
Ivano
What is happening in your first query on the 2nd row, is that Access isn't aware of what tblStat1 represents in your query.
The reason your 2nd query is working is because it uses an inner join on the relevant key. In order for SQL to be aware of what record in tblMain relates to which record in tblStat1, you need to use a join.
You can see in the generated code that it is updating your desired table, but joining onto the second table. The where condition is redundant as you're updating every record.
In 1st syntax, you can change:
UPDATE tblMain
SET tblMain.Stat1 = (SELECT Freq
FROM tblStat1
WHERE tblMain.Key = tblStat1.Key)

Multiple SQL Update Statements in single query

I am in a situation where I am having to update about 12,000 items in my DB.
Each row needs to mirror an excel file that I made previously.
I have made the file that creates each line of SQL statement, but I am not sure if I can run each line in a single query.
This is an example of what I am trying to do.
UPDATE [STORESQL].[dbo].[RPT_ITM_D] SET F1301='1.29' WHERE F01='0000000000001'
UPDATE [STORESQL].[dbo].[RPT_ITM_D] SET F1301='1.39' WHERE F01='0000000000002'
Will this work, or are there any better options for what I am trying to achieve?
Each item will have a unique value and the column to be changed will have a unique value as well. I don't see how I could make this work with a loop, or any other methods I've found so far. I realize that this might take a long time to process, but time is not an issue.
Thank you in advance
Something like this is the best you can do:-
UPDATE [STORESQL].[dbo].[RPT_ITM_D]
SET F1301 =
case F01
when '0000000000001' then '1.29'
when '0000000000002' then '1.30'
ELSE F1301
end
Other than that, running multiple updates is the way to go.
Yes, you could add all the single-line-Update-statements in one query like you are doing.
Take a look at MERGE e.g. something like:
MERGE INTO [STORESQL].[dbo].[RPT_ITM_D]
USING (
VALUES ('1.29', '0000000000001'),
('1.39', '0000000000002')
) AS source (F1301, F01)
ON F01 = source.F01
WHEN MATCHED THEN
UPDATE
SET F1301 = source.F1301;
...but using a table value constructor in this way would not scale to 12,000 rows! So look to first copying the data from Excel to a table on the server, then use the table as the source e.g.
MERGE INTO [STORESQL].[dbo].[RPT_ITM_D]
USING [STORESQL].[dbo].MyStagingTable AS source
ON F01 = source.F01
WHEN MATCHED THEN
UPDATE
SET F1301 = source.F1301;
If you have a significant amount of data to update, it may be advantageous to load the excel file into the database as a table, then update your table based on the data in this loaded table.
UPDATE RPT_ITM_D
SET F1301 = NewTable.Value
FROM RPT_ITM_D INNER JOIN NewTable ON (NewTable.F01 = RPT_ITEM_D.F01);
If you're on SQL server, you could use SSIS to load the file pretty quickly.
I think the best way is to import the Excel sheet into a table in your SQL database. From there you could be able to use a join to create a single update statement for all 12,000 items.
For information on how to import Excel sheet into SQL: http://msdn.microsoft.com/en-us/library/ms141209.aspx
The update statement would then look something like this:
UPDATE itemTable
SET F1301 = excelTable.<column with your value>
FROM [STORESQL].[dbo].[RPT_ITM_D] itemTable inner join [STORESQL].[dbo].[importedExcelTableName] excelTable on itemTable.F01 = excelTable.<column with the item code>
If you aren't sure if this would work safely, you can try this query for a single value by simple adding:
WHERE itemTable.F01 = '0000000000001'
You can use the concatenate function in Excel to frame a query, All you need to do is to frame a single update query and drag the same for the rest
concatenate("Update set =",,",where =
",,";")
Use the above format and drag the cell till the end or double click on the bottom right corner for Auto fill of the Update statement. I beleive this is the shortest way possible and run it in a single Go.
Make a unique constraint on the F01 column and then use an insert statement with an 'ON DUPLICATE KEY UPDATE' statement.
INSERT INTO [STORESQL].[dbo].[RPT_ITM_D] (F01, F1301)
VALUES
('0000000000001','1.29'),
('0000000000002','1.39')
ON DUPLICATE KEY UPDATE F1301 = VALUES(F1301);

How to do 2 update statements at a time?

update accounts set type=1 where id=2;
update accounts set type=3 where id=4;
At the same time? If you mean that you want to make sure no other queries affect the table before your queries are done, you're going to want to wrap them in a transaction.
exactly what you ask will be
update accounts set type = case id when 2 then 1 else 3 end where id in (2,4)
but in general this is of course impossibe.
This:
UPDATE ACCOUNTS t SET t.type = 1 WHERE t.id = 2; UPDATE ACCOUNTS t SET t.type = 3 WHERE t.id = 4;
...is acceptable SQL statement syntax - the ";" is a statement delimiter. The statements won't be executed simultaneously - nothing in a database is, everything is queued & processed in order of submission (though fiddling with isolation levels can work around that).
However, most APIs & IDEs prevent multiple statement execution like this in order to stop SQL injection attacks. What are you using that you find is stopping you from executing the statement?
If you want them to occur at once you could use a transaction:
SET autocommit=0;
START TRANSACTION;
update accounts set type=1 where id=2;
update accounts set type=3 where id=4;
COMMIT;
Note that you need to disable auto commit or the commit will occur when the first update occurs.
You may find this article interesting. I got more out of the comments than the article, but the article was interesting:
http://blog.bubble.ro/how-to-make-multiple-updates-using-a-single-query-in-mysql/
His technique probably won't work for you, but it is one approach.
The best bet would be to write a stored procedure and have it do the multiple updates, or, if there is some way for a program to determine the values for the second query, you could use a trigger, but I expect that won't help you.
It's not a generic solution but in this special case:
update accounts
set type = id - 1
where id = 2
or id = 4;
That's one statement...