INSERT into table wherever update_time is latest - sql

I have a table that has data about session. I want to insert hardcoded values for every new session row added at the latest time.
for example, given this table with 3 session rows information added at
2/10/2019 5:15 PM
I want to insert server1, and business values into the 3 rows (row 1-3) at the latest UDPATE_TIME, which in this case is
2/10/2019 5:15 PM
I use this query to get the latest update time:
$update_time = query "SELECT FORMAT(MAX([UPDATE_TIME]), 'M/d/yyyy h:mm tt') AS UPDATE_TIME FROM table"| Select -ExpandProperty UPDATE_TIME;
and i use this insert query to insert the values:
query "INSERT INTO table (SERVERNAME, Business_Name) VALUES ('server1', 'business')"
however, as you can see its inserting on a new row (row4), and instead i want to insert in rows that are already there 1-3, so that it becomes like this:
pseudo-code of query i am looking for:
query "INSERT INTO table (SERVERNAME, Business_Name) VALUES ('server1', 'business') wherever $update_time

I think you want an update. Something like this:
update [table]
set business_name = #business_name
where update_time = (select max(t2.update_time) from [table] t2);
Doing an update after the inserts seems dangerous -- different threads could be inserting data at the same time. However this answers the question that you did ask.

Related

Why is 'insert into select' statement in SQL inserting as a new row and not inserting correctly?

I have table 1.
I have another empty table 2 with the following columns.
I want to insert into table 2 by selecting from table 1 - so I write the query as:
insert into table2(employee,id,zone,url)
select employee, id, zone, concat('https://',employee,'.com/',id,'?',zone)
from table1
Now my table 2 looks like this,
Now for the authcode column, I do the following and insert it into the table2.
insert into table2(authcode)
SELECT CONVERT(VARCHAR(10),HASHBYTES('MD5', substring(URL,8,100)),2)
from table2.
But the insert happens differently like this AS AN ENTIRE NEW SET OF ROWS.
Can someone help me to insert the last column to the corresponding rows instead of it creating a new one?
What you should be doing is UPDATE the table to fill the column authcode, but you could do it all in 1 step while you are inserting the rows:
insert into table2(employee,id,zone,url, authcode)
select
employee,
id,
zone,
concat('https://',employee,'.com/',id,'?',zone),
CONVERT(VARCHAR(10),HASHBYTES('MD5', substring(concat('https://',employee,'.com/',id,'?',zone),8,100)),2)
from table1
or if you want to update:
update table2
set authcode = CONVERT(VARCHAR(10),HASHBYTES('MD5', substring(URL,8,100)),2)
where authcode is null
The result you are seeing is the intended behavior for an INSERT statement. It will always insert new rows.
If you want to modify existing rows your need to use an UPDATE statement.
You can either modify your INSERT to look like what #forpas has posted to get all this work done in one step. Another option is to modify the second INSERT to be an UPDATE like the following:
update table2
set authcode = CONVERT(VARCHAR(10),HASHBYTES('MD5', substring(URL,8,100)),2)

I have a table where I need to update or insert depending on field paramaters

I have spent many hours researching this problem and trying various solutions but I never quite find a suitable solution for my specific problem. I am new to SQL and some of the examples are confusing as well.
So here is my dilemma. I have a equipment table that tracks oil changes for specific units in a database. The table looks like this:
**id UnitID Posted_On Date_Completed Note OverDueBy**
1 BT-109F 2019-02-04 2019-02-14 Hrs Overdue 23
1 BT-108G 2020-01-17 2020-01-22 Days Overdue 12
1 BT-122K 2020-01-02 2020-01-16 Days Overdue 12
1 BT-109F 2019-02-04 Days Overdue 3
The example records above need to be created or updated by the query. The date completed is entered manually by the technician when he has completed the oil change.
What I want the query to do is, Check to see if a specific Unit has a record where the 'Date_Completed' field is empty, and if so update the 'OverDueBy' field to reflect the new value. If all the records for the specified Unit have the 'Date_Completed' fields filled in, then the query should create a new record will all fields filled in except for the 'Date_Completed' field.
Can anyone help me construct such a query?
Thanks
Clan
First create a unique partial index for the column UnitID:
CREATE UNIQUE INDEX idx_unit ON tablename(UnitID)
WHERE Date_Completed IS NULL;
so that only 1 row with Date_Completed=null is allowed for each UnitID.
So a statement like this:
INSERT INTO tablename(id, UnitID, Posted_On, Date_Completed, Note, OverDueBy)
VALUES (?, 'BT-109F', ?, null, ?, ?)
ON CONFLICT(UnitID) WHERE Date_Completed IS NULL DO UPDATE
SET OverDueBy = ?;
will insert the new values only if there is no row already for UnitID='BT-109F' with null in Date_Completed.
But if there is such a row then it will update the column OverDueBy.
I'm not sure what values you want to insert or what will be the updated value so replace the ? with the appropriate values.
Firstly I would use a view rather than a table to store any calculated data - it reduces storage overheads and will update the calculation every time the view is opened.
If you're using SQLite you should be able to get the overdue by subtracting the Posted_On from its function to return today's date something like date('now') or julianday('now') - read up on and test the functions to ensure it does what you want.
So along the lines of:-
create view MyView as select *, julianday('now') - julianday(Posted_On) as OverDueBy from ClansTable where Date_Completed is null;
If you want to store a snapshot you can always create a table from a view in any case:-
create table MyStoredOverduesOn4thFeb as select * from MyView;
You can find your units that have all Date_Completed and create a single new record like so:-
Create table CompletedUnits as select id, UnitID, max(posted_on) as latest_posted_on, '' as Date_Completed from ClansTable group by id, UnitID having count(*) = count(Date_Complete);
Test this SQL and see if you can get it working - note I've created a text field for the date. Apparently there is no date/datetime data type as such:-
https://www.sqlitetutorial.net/sqlite-date/
Hope this helps,
Phil
I think you need something like this:
MERGE INTO EQUIPMENT A
USING (SELECT * FROM EQUIPMENT B WHERE DATE_COMPLETED IS NULL) C
ON (A.UNITID=C.UNITID)
WHEN MATCHED THEN UPDATE SET A.OVERDUEBY="new value"
WHEN NOT MATCHED THEN INSERT (A.id,A.UnitID,A.Posted_On,A.Date_Completed,A.Note,A.OverDueBy)
VALUES (C.id,C.UnitID,C.Posted_On,NULL,C.Note,C.OverDueBy)
Not sure where new values from update will come from. It's not clear in your question. But something like this could work.

Insert row to database based on form values not currently in database

I am using Access 2013 and I am trying to insert rows to a table but I don't want any duplicates. Basically if not exists in table enter the data to table. I have tried to using 'Not Exists' and 'Not in' and currently it still does not insert to table. Here is my code if I remove the where condition then it inserts to table but If I enter same record it duplicates. Here is my code:
INSERT INTO [UB-04s] ( consumer_id, prov_id, total_charges, [non-covered_chrgs], patient_name )
VALUES ([Forms]![frmHospitalEOR]![client_ID], [Forms]![frmHospitalEOR]![ID], Forms![frmHospitalEOR].[frmItemizedStmtTotals].Form.[TOTAL BILLED], Forms![frmHospitalEOR].[frmItemizedStmtTotals].Form.[TOTAL BILLED], [Forms]![frmHospitalEOR]![patient_name])
WHERE [Forms]![frmHospitalEOR]![ID]
NOT IN (SELECT DISTINCT prov_id FROM [UB-04s]);
You cannot use WHERE in this kind of SQL:
INSERT INTO tablename (fieldname) VALUES ('value');
You can add a constraint to the database, like a unique index, then the insert will fail with an error message. It is possible to have multiple NULL values for several rows, the unique index makes sure that rows with values are unique.
To avoid these kind of error messages you can build a procedure or use code to check data first, and then perform some action - like do the insert or cancel.
This select could be used to check data:
SELECT COUNT(*) FROM [UB-04s] WHERE prov_id = [Forms]![frmHospitalEOR]![ID]
It will return number of rows with the spesific value, if it is 0 then you are redy to run the insert.

SCOPE_IDENTITY for multiple records

The below query inserts many records in a transaction. I want to fetch the newly created incremental identifier and use it in next INSERT statement
For a single record I can use like below
SELECT #new_emp_id= SCOPE_IDENTITY()
What about SCOPE_IDENTITY for multiple records? Or we can insert it into temp table and loop through it?
INSERT EmployeeBenifits(EmployeeId,BenifitID,StartdateTime,EndDateTime)
SELECT #new_emp_id,BenifitID,GetDate(),#PassedEndDate FROM Benifits
INSERT EmployeeBenifitDetails(EmpBenId,Desc)
SELECT EmpBenId,'Created Details' FROM #NewlyInsertedEmplBenifits
You should have a look at the OUTPUT clause:
INSERT INTO dbo.EmployeeBenefits(EmployeeId, BenefitID, StartdateTime, EndDateTime)
OUTPUT Inserted.EmployeeBenefitId, Inserted.EmployeeID, Inserted.BenefitID -- or whatever you want to return here
SELECT
#new_emp_id, BenefitID, GetDate(), #PassedEndDate
FROM
dbo.Benefits
Basically, the OUTPUT clause can return a result set of columns for each row that has been inserted (also works with the DELETE and UPDATE statements).
See MSDN documentation for more details
You can also send the OUTPUT rows to a temporary table (or table variable) to be further processed later on.

Does DB2 have an "insert or update" statement?

From my code (Java) I want to ensure that a row exists in the database (DB2) after my code is executed.
My code now does a select and if no result is returned it does an insert. I really don't like this code since it exposes me to concurrency issues when running in a multi-threaded environment.
What I would like to do is to put this logic in DB2 instead of in my Java code.
Does DB2 have an insert-or-update statement? Or anything like it that I can use?
For example:
insertupdate into mytable values ('myid')
Another way of doing it would probably be to always do the insert and catch "SQL-code -803 primary key already exists", but I would like to avoid that if possible.
Yes, DB2 has the MERGE statement, which will do an UPSERT (update or insert).
MERGE INTO target_table USING source_table ON match-condition
{WHEN [NOT] MATCHED
THEN [UPDATE SET ...|DELETE|INSERT VALUES ....|SIGNAL ...]}
[ELSE IGNORE]
See:
http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=/com.ibm.db2.udb.admin.doc/doc/r0010873.htm
https://www.ibm.com/support/knowledgecenter/en/SS6NHC/com.ibm.swg.im.dashdb.sql.ref.doc/doc/r0010873.html
https://www.ibm.com/developerworks/community/blogs/SQLTips4DB2LUW/entry/merge?lang=en
I found this thread because I really needed a one-liner for DB2 INSERT OR UPDATE.
The following syntax seems to work, without requiring a separate temp table.
It works by using VALUES() to create a table structure . The SELECT * seems surplus IMHO but without it I get syntax errors.
MERGE INTO mytable AS mt USING (
SELECT * FROM TABLE (
VALUES
(123, 'text')
)
) AS vt(id, val) ON (mt.id = vt.id)
WHEN MATCHED THEN
UPDATE SET val = vt.val
WHEN NOT MATCHED THEN
INSERT (id, val) VALUES (vt.id, vt.val)
;
if you have to insert more than one row, the VALUES part can be repeated without having to duplicate the rest.
VALUES
(123, 'text'),
(456, 'more')
The result is a single statement that can INSERT OR UPDATE one or many rows presumably as an atomic operation.
This response is to hopefully fully answer the query MrSimpleMind had in use-update-and-insert-in-same-query and to provide a working simple example of the DB2 MERGE statement with a scenario of inserting AND updating in one go (record with ID 2 is updated and record ID 3 inserted).
CREATE TABLE STAGE.TEST_TAB ( ID INTEGER, DATE DATE, STATUS VARCHAR(10) );
COMMIT;
INSERT INTO TEST_TAB VALUES (1, '2013-04-14', NULL), (2, '2013-04-15', NULL); COMMIT;
MERGE INTO TEST_TAB T USING (
SELECT
3 NEW_ID,
CURRENT_DATE NEW_DATE,
'NEW' NEW_STATUS
FROM
SYSIBM.DUAL
UNION ALL
SELECT
2 NEW_ID,
NULL NEW_DATE,
'OLD' NEW_STATUS
FROM
SYSIBM.DUAL
) AS S
ON
S.NEW_ID = T.ID
WHEN MATCHED THEN
UPDATE SET
(T.STATUS) = (S.NEW_STATUS)
WHEN NOT MATCHED THEN
INSERT
(T.ID, T.DATE, T.STATUS) VALUES (S.NEW_ID, S.NEW_DATE, S.NEW_STATUS);
COMMIT;
Another way is to execute this 2 queries. It's simpler than create a MERGE statement:
update TABLE_NAME set FIELD_NAME=xxxxx where MyID=XXX;
INSERT INTO TABLE_NAME (MyField1,MyField2) values (xxx,xxxxx)
WHERE NOT EXISTS(select 1 from TABLE_NAME where MyId=xxxx);
The first query just updateS the field you need, if the MyId exists.
The second insertS the row into db if MyId does not exist.
The result is that only one of the queries is executed in your db.
I started with hibernate project where hibernate allows you to saveOrUpdate().
I converted that project into JDBC project the problem was with save and update.
I wanted to save and update at the same time using JDBC.
So, I did some research and I came accross ON DUPLICATE KEY UPDATE :
String sql="Insert into tblstudent (firstName,lastName,gender) values (?,?,?)
ON DUPLICATE KEY UPDATE
firstName= VALUES(firstName),
lastName= VALUES(lastName),
gender= VALUES(gender)";
The issue with the above code was that it updated primary key twice which is true as
per mysql documentation:
The affected rows is just a return code. 1 row means you inserted, 2 means you updated, 0 means nothing happend.
I introduced id and increment it to 1. Now I was incrementing the value of id and not mysql.
String sql="Insert into tblstudent (id,firstName,lastName,gender) values (?,?,?)
ON DUPLICATE KEY UPDATE
id=id+1,
firstName= VALUES(firstName),
lastName= VALUES(lastName),
gender= VALUES(gender)";
The above code worked for me for both insert and update.
Hope it works for you as well.