Automatic update of values in SQL Server - sql-server

For example I have a table tb with columns :
order_id | date_ordered | due_date | status
Are there any out of the box solution where I can automatically update status column when the current time (from server) reaches the value of the due_date column? How do I do it?
Thanks in advance.
UPDATE :
Something like this :
test1 | 2016-03-30 09:19:06.610 | 2016-03-30 11:19:06.610 | NEW
test2 | 2016-03-30 09:22:43.513 | 2016-03-30 11:22:43.513 | NEW
test3 | 2016-03-30 09:06:03.627 | 2016-03-30 11:06:03.627 | NEW
When the server time reaches 2016-03-30 11:19:06.610, test1's status will change value say, overdue

It depends on what you mean by "out of the box solution". You could create a sql server agent job, which checks every minute if the value due_date is less or equal to the current date and time and change the state column.
A computed column might be another, much simpler solution.
A table like this might suffice:
CREATE TABLE tb_test (
order_id INT PRIMARY KEY,
date_ordered DATETIME,
due_date DATETIME,
[status] as
CASE WHEN due_date <= GETDATE() THEN 'overdue'
ELSE 'new' END
);

Related

Execute Stored Procedure using Trigger on VIEW when multiple columns are updated with specific values

I have a VIEW (in SQL SERVER) containing the following columns:
itemID[vachar(50)]|itemStatus [vachar(20)]|itemCode[vachar(20)]|itemTime[varchar(5)]
The itemID column contains id values that do not change. The remaining 3 rows however get updated periodically. I understand it is more difficult create a trigger on a VIEW.
An example of the table containing data would be:
|itemID|imtemStatus|itemCode|itemTime|
|------|-----------|--------|--------|
| 1 | OK | 30 | 00:10 |
|------|-----------|--------|--------|
| 2 | OK | 40 | 02:30 |
|------|-----------|--------|--------|
| 3 | STOPPED | 30 | 00:01 |
|------|-----------|--------|--------|
When itemStatus = STOPPED & itemCode = 30
I would like to execute a stored procedure (sp_Alert) passing the itemID as a parameter
Any help would be greatly appreciated
Since a trigger is at least "not easy", I'd like to propose an ugly but functional way out. You can create a stored procedure that checks ItemCode and ItemStatus. If they match your criteria you can start the sp_Alert from this procedure.
create procedure check_status as
if (select 1
from vw_itemstatus
where itemStatus = 'STOPPED'
and itemCode = 30) is not null
begin
declare #item_id int
set #item_id = (select itemID
from vw_itemstatus
where itemStatus = 'STOPPED'
and itemCode = 30)
exec sp_Alert #item_id
end
Depending on how critical this functionality is and how many resources you can use for it, you can schedule this procedure via the SQL Server Agent. If you run this with a short interval, it will work "similar" to what you had in mind.

SQL Consecutive Sequence Number gets messed up with ORDER BY

I am working on Windows Form Application and it accesses database in SQL Server 2014. I have EmployeeTable which I retrieve data from, and display all the records in DataGridView. In this table, I have a column SequenceID, which basically increments from 1 up to the number of records in this table, but this is not the same as AUTO INCREMENT in that SequenceID gets updated each time the table is modified, and keeps the numerical order no matter how many times new records get inserted or some records are deleted. For example, if the data looks like
SequenceID | Name
1 | John
2 | Mary
3 | Robert
and Mary is removed, then the resulting table needs to look like
SequenceID | Name
1 | John
2 | Robert
In order to achieve this, I used the best answer by zombat from Update SQL with consecutive numbering, and it was working great until I used ORDER BY expression.
This EmployeeTable also has DateAdded column, containing the date when the record was inserted. I need to display all records ordered by this DateAdded column, with the oldest record shown at the top and the newest at the bottom in addition to the correct SequenceID order. However, it gets messed up when a record is deleted, and a new one is inserted.
If I insert 3 records like,
SequenceID | Name | DateAdded
1 | John | 9/25/2017
2 | Mary | 9/26/2017
3 | Robert | 9/27/2017
and remove Mary, it becomes
SequenceID | Name | DateAdded
1 | John | 9/25/2017
2 | Robert | 9/27/2017
and this is good so far. However, if I add another record Tommy on, say, 9/28/2017, which should be added at the bottom because it is the newest, it results in something like,
SequenceID | Name | DateAdded
1 | John | 9/25/2017
3 | Robert | 9/27/2017
2 | Tommy | 9/28/2017
The ORDER BY is working fine, but it messes up the SequenceID, and I am not sure why this is happening. All I am doing is,
SELECT *
FROM EmployeeTable
ORDER BY DateAdded
I tried placing zombat's SQL command both before and after this SQL command, but neither worked. It seems to me like when I delete a row, the row has an invisible spot, and a new record is inserted in there.
Is there any way to fix this so I can order the records by DateAdded and still have the SequenceID working correctly?
If you need id for GUI (presentation only) you could use:
SELECT ROW_NUMBER() OVER(ORDER BY DateAdded) AS sequenceId, Name, DateAdded
FROM EmployeeTable
ORDER BY DateAdded;
EDIT:
I am trying to update the SequenceID, but it is not getting updated
You should not try to reorder your table every time. It doesn't make sense.

SQL Server 2008 exec stored procedure on 3rd strike

I've been asked to create a process that triggers a stored procedure when an employee hits their 3rd strike. The strikes relate to absence, so if an employee is off 3 times in a 3 month period it hits the trigger.
But... this only applies to single instances of absence, so if a person is off; for example on the 11/01/2016, 12/01/2016 & 13/01/2016 then this is one instance. Meaning I can't do a count on the number of days off sick.
Data I have available and is a fixed process I can't update:
Date | EmpID | EmpName
01/01/2016 | JS01 | John Spartan
02/01/2016 | JS01 | John Spartan
03/01/2016 | JS01 | John Spartan
08/01/2016 | JS01 | John Spartan
19/02/2016 | JS01 | John Spartan
12/02/2016 | JS01 | John Spartan
Based on the above there are more than 2 instances. So this would trigger the procedure
IF EXISTS (<Query Here>)
BEGIN
EXEC usp_ThreeStrikes
END
Is there a way to do this in T-SQL?
If you can't add columns to help query with the task (eg. InstanceID query would group by to find out number of instances), I think best solution would be to create aggregate CLR function for the task.
https://msdn.microsoft.com/en-us/library/ms131056.aspx
You can try the below approach:
Add an additional column to your table to differentiate if the record should be considered for next strike or not (means after 1 instance, it should not be considered the 2nd time)
Create a SQL Update Trigger to call the procedure, based on the below condition:
Get the records whose column is considered for next strike (same column what you have created in first step)
For those particular records check the count if its greater or equal to 3 and call the stored procedure
For those particular records, update the additional column (created in step 1) to not consider it for the subsequent strikes
Hope this helps.
Here you have a query that lists the empid's that were absent three or more times per quarter. You can modify this query in your trigger to only select in the empids/quarters that are present in the inserted table in your trigger.
PS: I've added some random absences to show that the query only selectes when the number of absences is three or more.
CREATE TABLE #absences(dt DATE,empid NVARCHAR(128),empname NVARCHAR(128));
INSERT INTO #absences(dt,empid,empname)VALUES
('20151212','JS02','John Spartan2'),
('20151213','JS02','John Spartan2'),
('20151010','JS01','John Spartan'),
('20151011','JS01','John Spartan'),
('20151217','JS02','John Spartan2'),
('20151219','JS02','John Spartan2'),
('20160101','JS01','John Spartan'),
('20160102','JS01','John Spartan'),
('20160103','JS01','John Spartan'),
('20160108','JS01','John Spartan'),
('20160201','JS02','John Spartan2'),
('20160203','JS02','John Spartan2'),
('20160219','JS01','John Spartan'),
('20160212','JS01','John Spartan');
SELECT
empid,
[quarter]=DATEADD(QUARTER,DATEDIFF(QUARTER,0,o.dt),0)
FROM
#absences AS o
WHERE
NOT EXISTS (
SELECT 1
FROM #absences AS i
WHERE i.empid=o.empid AND
DATEDIFF(QUARTER,0,i.dt)=DATEDIFF(QUARTER,0,o.dt) AND
i.dt=DATEADD(DAY,-1,o.dt)
)
GROUP BY
empid,
DATEDIFF(QUARTER,0,o.dt)
HAVING
COUNT(*)>=3;
DROP TABLE #absences;
Result:
+-------+-------------------------+
| empid | quarter |
+-------+-------------------------+
| JS02 | 2015-10-01 00:00:00.000 |
| JS01 | 2016-01-01 00:00:00.000 |
+-------+-------------------------+

SQL Query to return one row or field based on 3 conditions

I am working on a project where I'm trying to have the results of a SQL query emailed out when a certain log message appears in the SQL Server database.
My first goal is to isolate the data I need. The relevant tables are as follows:
System | Time | Log | Index
1001 |7/16/2015 7:22 |Fail |1729943
1002 |7/17/2015 10:26|Success |1743789
1002 |7/18/2015 10:26|Success |1743799
1003 |7/22/2015 6:14 |Timeout |1771793
What I'm interested in specifically is the last Time when system 1002 generates Success in Log. Seems simple enough but System and Log are not unique records and the following:
SELECT *
FROM DB.LogFiles
WHERE System ='1002' and Log ='Success'
Returns 2 rows:
System | Time | Log | Index
1002 | 7/17/2015 09:43 | Success | 1743789
1002 | 7/18/2015 10:26 | Success | 1743799
I'm in just interested in the last Time this condition occurred so the last row:
1002 | 7/18/2015 10:26 | Success | 1743799
That process will repeat everyday so the next day I would see the following records:
System | Time | Log | Index
1002 | 7/17/2015 09:43 | Success | 1743789
1002 | 7/18/2015 10:26 | Success | 1743799
1002 | 7/9/2015 11:42 | Success | 1748752
Of which I would like to be notified of again only the new and last record
1002 | 7/9/2015 11:42 | Success | 1749261
The end goal of the project is to have the query scheduled to run every few hours and looking to see if a new ‘Success’ record has been entered. If it has than generate an email. I’m not sure if that portion can be done in SQL however, and I may need to look at something outside of that to accomplish this. Any assistance or insight on at least the SQL portion would be most helpful.
If I understand correctly that the index is unique and the higher the value the newer the record then you can do something like this.
SELECT a.system, a.time, a.log, a.index
FROM log_files a
WHERE a.System ='1002' and a.Log ='Success'
AND a.index = (SELECT MAX(z.index) FROM log_files z
WHERE z.System = a.System and z.Log = a.Log)
WITH X AS
(
SELECT [System]
,[Time]
,[Log]
,[Index]
,ROW_NUMBER() OVER (PARTITION BY [System]
ORDER BY CAST([Time] AS DATETIME) DESC) rn
FROM TableName
)
SELECT [System]
,[Time]
,[Log]
,[Index]
FROM X
WHERE rn = 1
Add a new field (Flag) to your log table with default to FALSE. Whenever you send an email regarding to a record, set the Flag field to TRUE/
every time you want to send the email, just check the record with highest date and only send email if the Flag field is False. If the Flag field is TRUE, just ignore it.

Update column of different table based on manipulated result of another table

I have a table1 like below having more than 400k records.Below I'm just showing example, how it look likes. I want to write some query to iterate through each row and find its corresponding date; if all dates are present for the account ID , then I have to update another table2 "Yes". And, if any one of the date is null (for any account ID) then I have to update table2 flag as "No".
This is my source table1.
Table1
Account ID | Date
----------- |------------
1 | 12-03-2015
1 | 11-03-2015
1 | 11-04-2015
1 | 01-03-2015
2 | 06-03-2015
2 | 11-03-2015
2 | Null
2 | 01-03-2015
This is how the table2 result will look like (after query execution)
Table2
Account ID | Flag
-----------|------
1 | Yes
2 | No
2ndly, if after few days, Date of Account ID is changed from Null to an actual date (say 07-07-2015), then Table2 "Account ID 2" value should change from "No" to "Yes". So after few days the Table2 should look like this
Account ID | Flag
-----------|------
1 | Yes
2 | Yes
Hope I have explained it correctly.I'm thinking to use cursor, however, I'm not sure how to use this and will cursor really solve this problem? Is there any other ways to achieve this? Checked on net, however, not able to get suitable solution, please help?
You need to change your mindset from looking at every row. This is a very simple set based solution. You should also use better names than DATE and Flag but whatever, this will return the desired output you are after.
select AccountID
, case MIN(case when [Date] is null then '' else [DATE] end) when '' then 'No' else 'Yes' end as Flag
from Table1
group by AccountID

Resources