I want to provide an EndDate when the MainAccountNum already exist. The endDate should be applied to the MainAccountNumb with the earliest startDate.
So If I have a create table statement like this:
Create Table ods.CustomerId(
ScreenDate INT NOT NULL,
CustomerNum nvarchar(40) NOT NULL,
MainAccountNum nvarchar(40) not null,
ServiceNum nvarchar(40) not null,
StartDate datetime not null,
EndDate datetime not null,
UpdatedBy nvarchar(50) not null);
and say I encounter something in the CustomerNum, MainAccountNum, StartDate, and EndDate like below:
1467823,47382906,2019-08-26 00:00:00.000, Null
1467833,47382906,2019-09-06 00:00:00.000, null
When the second record is inserted with that same MainAccountNum the first record should get the startDate of the New Record. The startDate has a default constraint as GetDat() so in the end it should look like:
1467823,47382906,2019-08-26 00:00:00.000,2019-09-06 00:00:00.000
1467833,47382906,2019-09-06 00:00:00.000, null
Please Provide code examples of how this can be accomplished
In the stored procedure used to insert new record, have something like
begin tran
declare #startDate datetime
select top 1 #oldStartDate = StartDate
from ods.CustomerId
where MainAccountNum = #mainAccountNum
order by StartDate asc
if ##rowcount > 0
update ods.CustomerId set EndDate = #startDate
where MainAccountNum = #mainAccountNum and StartDate = #oldStartDate
insert ... <your new record here>
commit
I am assuming that (MainAccountNum, StartDate) tuple is unique and can be used as a key. If not, you have to use whatever is unique for your update statement.
Related
I want to provide an EndDate when the MainAccountNum already exist. The endDate should be applied to the MainAccountNumb with the earliest startDate.
So If I have a create table statement like this:
Create Table ods.CustomerId(
ScreenDate INT NOT NULL,
CustomerNum nvarchar(40) NOT NULL,
MainAccountNum nvarchar(40) not null,
ServiceNum nvarchar(40) not null,
StartDate datetime not null,
EndDate datetime not null,
UpdatedBy nvarchar(50) not null);
and say I encounter something in the CustomerNum, MainAccountNum, StartDate, and EndDate like below:
1467823,47382906,2019-08-26 00:00:00.000, Null
1467833,47382906,2019-09-06 00:00:00.000, null
When the second record is inserted with that same MainAccountNum the first record should get the startDate of the New Record. The startDate has a default constraint as GetDat() so in the end it should look like:
1467823,47382906,2019-08-26 00:00:00.000,2019-09-06 00:00:00.000
1467833,47382906,2019-09-06 00:00:00.000, null
Please Provide code examples of how this can be accomplished
I would like to apply an update to the current records in my table that do not have an endDate but have this same situation. How would I apply that update to where I give the previous record an endDate please provide me with code to solve this issue. Thanks so much
Your CustomerId table has EndDate as not null, how did they end up being null. Anyway try this:
update CustomerId
set EndDate = (select min(t2.StartDate) from CustomerId t2
where t2.MainAccountNum = t1.MainAccountNum and t2.StartDate > t1.StartDate)
from CustomerId t1
where t1.EndDate is null
For clarification, are you looking for a trigger function that will update all rows with null EndDate fields and the same MainAccountNum as a newly inserted row?
if so, the following should work:
CREATE TRIGGER cust_trg
ON CustomerId
AFTER INSERT
AS
BEGIN
UPDATE CustomerId
SET EndDate = inserted.StartDate
WHERE EndDate IS NULL AND MainAccountNum = inserted.MainAccountNum AND StartDate = (SELECT MIN(StartDate) FROM CustomerId WHERE MainAccountNum = inserted.MainAccountNum AND EndDate IS NULL)
END;
Note that with the schema as written there should be no null values in EndDate column, so unless the schema is changed this trigger will never fire.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
Intending to update Table6 with the following procedure. I have set variables and they are correctly addressed but how do I define value for the 2 types of variables. there are search variables and update variables
Procedure with condition if the cell has NULL value than add whatever the Variable has but if it already has value then leave its original value/don't overwrite it.
CREATE PROCEDURE dbo.[Learning]
#StartDate DATE NULL,
#EndDate DATE NULL,
#Data VARCHAR(30) NULL,
#Cond_CID INT NOT NULL,
#Cond_PID INT NOT NULL,
#Cond_SSC VARCHAR(3) NOT NULL
AS
BEGIN
BEGIN
UPDATE temp.dbo.Table6
SET StartDate = ISNULL(StartDate,#StartDate)
,EndDate = ISNULL(EndDate,#EndDate)
,Data = ISNULL(Data,#Data)
WHERE Table6.CID = #Cond_CID AND TABLE6.PID = #Cond_PID AND TABLE6.SSC = #Cond_SSc
The table and data insert
CREATE TABLE temp.dbo.Table6
(
CID INT NOT NULL,
PID INT NOT NULL,
SSC VARCHAR(3) NULL,
StartDate DATE NULL,
EndDate DATE NULL,
Data VARCHAR(30) NULL
)
INSERT INTO temp.dbo.Table6
VALUES
(1001, 1333,'OP', GETDATE(), GETDATE(), 'OP2001156519952012'),
(1002, 1245,'OR', GETDATE(), NULL, 'OR20121005'),
(1003, 1116,'OP', GETDATE(), NULL, 'OP20131215'),
(1004, 1234,'OP', GETDATE(), GETDATE(), 'OP2001156519952012')
SELECT * FROM temp.dbo.Table6
sample data which has null values and this procedure will be used to populate data into the table.
It seems like you want to prevent the (3) search parameters to be NULLs, but when you set those parameters as NOT NULL SQL Server will complain about it, and throw
Msg 11555 Level 15 State 1 Line 7
The parameter 'ParameterName' has been declared as NOT NULL. NOT NULL parameters are only supported with natively compiled modules, except for inline table-valued functions.
Also, I think your first 3 parameters shouldn't be NULL too, cause if you pass NULLs then your UPDATE won't do anything, just set your columns to NULL again.
You can check for NULLs in the body of your SP, and if one of them IS NULL then raise an error as
CREATE PROCEDURE dbo.[Learning]
(
#StartDate DATE,
#EndDate DATE,
#Data VARCHAR(30),
#Cond_CID INT,
#Cond_PID INT,
#Cond_SSC VARCHAR(3)
)
AS
BEGIN
IF (#Cond_CID IS NULL OR #Cond_PID IS NULL OR #Cond_SSC IS NULL
OR #StartDate IS NULL OR #EndDate IS NULL OR #Data IS NULL
)
BEGIN
RAISERROR('Null values not allowed for the 3 last parameters!', 16, 1)
END
ELSE
BEGIN
UPDATE temp.dbo.Table6
SET StartDate = ISNULL(StartDate,#StartDate)
,EndDate = ISNULL(EndDate,#EndDate)
,Data = ISNULL(Data,#Data)
WHERE Table6.CID = #Cond_CID
AND
TABLE6.PID = #Cond_PID
AND
TABLE6.SSC = #Cond_SSc
END
END
or by Creating Natively Compiled Stored Procedures.
If i have a table variable like that how to loop over this var to make some processing :
DECLARE #userData TABLE(
userId int NOT NULL,
dayDate datetime NOT NULL,
transIn datetime NULL,
transOut datetime NULL,
attIn datetime NULL,
attOut datetime NULL,
MissionIn datetime NOT NULL,
MissionOut datetime NOT NULL,
empState varchar(10) NULL
);
INSERT INTO #userData
SELECT userid, trans_date,transtime_in,transtime_out,att_start_time,att_end_time,#Mission_fromdatetime,#Mission_todatetime,day_flag
FROM datatable_o a
WHERE a.userid = #userid AND a.trans_date = #date ORDER BY transtime_in ;
According to the comments the Whole case :
If the work starts at : att_start_time and ends at att_end_time (work period]
Every employee could check -in and check-out many times in the same date so we could follow him .
the check-in stored in transtime_in
and check-out stored in transtime_out
and i have day_flag so i could know the day is 'W' work day or 'E' weekend
Now considering all these information in addition to the emp_num ,date
I want to calc for the an employee External mission over time :
I have four cases :
No check-in-out && Not work day [weekend] So the employee
should take all the mission period as overtime
No check-in-out && Work day [Absent] so the employee should
take only the mission period out of the work period
There are check-in-outs && Not work day [week end] so the
employee should take only the mission period out of these
check-ins-outs
There are check-ins-outs && work day so the employee should take
only the mission period out of these check-ins-outs and at the same
time out of work period .
Example :
emp_num date att_start att_end mission-in mission-out
672 2015-3-4 07:05:00 13:30:00 12:12:00 20:00:00
emp_num date trans_in trans_out
672 2015-3-4 06:54:00 11:10:00
672 2015-3-4 12:00:00 14:05:00
You can loop through your table by taking help from a copy of that table:
with regard to your question assuming your table is:
DECLARE #userData TABLE(
userId int NOT NULL,
/*Other fields*/
);
and the data of your table is:
INSERT INTO #userData
/*A SELECT or values*/
now create a copy of your table as:
DECLARE #userData_2 TABLE(
userId int NOT NULL,
/*Structure should be the same as #userData*/
);
INSERT INTO #userData_2
SELECT * FROM #userData
now you can do the loop and do whatever you want:
DECLARE #userId INT
WHILE EXISTS (SELECT * FROM #userData_2)
BEGIN
SET #userId=(SELECT TOP 1 userId FROM #userData)
/*
DO YOUR TRANSACTION HERE
*/
DELETE FROM #userData_2 WHERE userId=#userID
END
NOTICE: this assumes the userId is unique, if not then you need to have a unique field, or use a composite fields instead of userId.
How to check if a DATE being inserted or updated in a table is between two other dates from another table.
Adicional Info:
I have 2 tables:
Activity:
StartDate date NOT NULL
EndDate date NULLABLE
SubActivity:
SubActivityDate date NOT NULL
When EndDate IS NOT NULL I check if: StartDate ≤ SubActivityDate ≤ EndDate
When EndDate IS NULL I check if: StartDate ≤ SubActivityDate
I was trying to write a BEFORE INSERT trigger but I figured out that it doesnt exist.
So what I could do?
AFTER INSERT?
INSTEAD OF INSERT? looks better than 1st solution
Is it possible just with CHECK Constraints?
How do I solve this problem?
EDIT
I just went with the CHECK constraint + function:
constraint:
ALTER TABLE SubActivity
ADD CONSTRAINT CK_SubActivity_Date CHECK (dbo.ufnIsSubactivityDateValid(ActivityID, SubActivityDate) = 1);
function:
CREATE FUNCTION ufnIsSubactivityDateValid(#ActivityID [int], #SubActivityDate [date])
RETURNS [bit]
AS
BEGIN
DECLARE #StartDate date, #EndDate date;
SELECT #StartDate = StartDate , #EndDate = EndDate
FROM Activity
WHERE ActivityID = #ActivityID;
IF (#SubActivityDate < #StartDate )
RETURN 0; -- out of range date
IF (#EndDate IS NULL)
RETURN 1; -- good date
ELSE
IF (#SubActivityDate > #EndDate)
RETURN 0; -- out of range date
RETURN 1; -- good date
END
What is best is situation by situation. Constraint guarantees proper values but rollsback an entire transaction over one wrong value. Triggers allow you more control but are a little more complex because of it.
Create and Populate your Table
IF OBJECT_ID('dbo.yourTable') IS NOT NULL
DROP TABLE yourTable;
CREATE TABLE yourTable
(
ID INT IDENTITY(1,1) PRIMARY KEY,
StartDate DATE NOT NULL,
SubActivityDate DATE NULL,
EndDate DATE NULL
);
INSERT INTO yourTable(StartDate,SubActivityDate,EndDate)
VALUES ('20150101',NULL,NULL),
('20150101',NULL,NULL),
('20150101',NULL,'20150201'),
('20150101',NULL,'20150201');
Constraint Method:
ALTER TABLE yourTable
ADD CONSTRAINT chk_date CHECK (StartDate <= SubActivityDate AND SubActivityDate <= EndDate);
UPDATE yourTable
SET SubActivityDate = CASE
WHEN ID = 1 THEN '20140101' --bad
WHEN ID = 2 THEN '20150102' --good
WHEN ID = 3 THEN '20140101' --bad
WHEN ID = 4 THEN '20150102' --good
END
SELECT *
FROM yourTable;
Since there is at least value that does not fit the constraint, the whole transaction is rolled back and the result is that SubActivitDate stays NULL.
Results:
ID StartDate SubActivityDate EndDate
----------- ---------- --------------- ----------
1 2015-01-01 NULL NULL
2 2015-01-01 NULL NULL
3 2015-01-01 NULL 2015-02-01
4 2015-01-01 NULL 2015-02-01
Trigger Method(My Preferred Method)
CREATE TRIGGER trg_check_date ON yourTable
INSTEAD OF UPDATE
AS
BEGIN
UPDATE yourTable
SET SubActivityDate = CASE
WHEN inserted.SubActivityDate >= inserted.StartDate AND ((Inserted.EndDate IS NULL) OR Inserted.SubActivityDate <= Inserted.EndDate) THEN inserted.SubActivityDate
ELSE NULL
END
FROM yourTable
INNER JOIN inserted
ON yourTable.ID = inserted.ID
END;
GO
UPDATE yourTable
SET SubActivityDate = CASE
WHEN ID = 1 THEN '20140101' --bad
WHEN ID = 2 THEN '20150102' --good
WHEN ID = 3 THEN '20140101' --bad
WHEN ID = 4 THEN '20150102' --good
END
SELECT *
FROM yourTable
This method allows the proper values and simply returns null for improper ones. If you wanted, you could even export the incorrect values from the inserted table into a log table so you know which ones didn't work. Or raise an error message and list the values that didn't work. In short, you have total control of the situation.
Results:
ID StartDate SubActivityDate EndDate
----------- ---------- --------------- ----------
1 2015-01-01 NULL NULL
2 2015-01-01 2015-01-02 NULL
3 2015-01-01 NULL 2015-02-01
4 2015-01-01 2015-01-02 2015-02-01
constraint:
ALTER TABLE SubActivity
ADD CONSTRAINT CK_SubActivity_Date CHECK (dbo.ufnIsSubactivityDateValid(ActivityID, SubActivityDate) = 1);
function:
CREATE FUNCTION ufnIsSubactivityDateValid(#ActivityID [int], #SubActivityDate [date])
RETURNS [bit]
AS
BEGIN
DECLARE #StartDate date, #EndDate date;
SELECT #StartDate = StartDate , #EndDate = EndDate
FROM Activity
WHERE ActivityID = #ActivityID;
IF (#SubActivityDate < #StartDate )
RETURN 0; -- out of range date
IF (#EndDate IS NULL)
RETURN 1; -- good date
ELSE
IF (#SubActivityDate > #EndDate)
RETURN 0; -- out of range date
RETURN 1; -- good date
END
I am trying to accomplish to update the column ListPrice adding 25 to its current value where the name is All-Purpose Bike Stands and update SellStartDate to tomorrow's date in the table Production.Product.
Using that updated price I want to insert a row into the table Production.ProductListHistory with the new ListPrice and also update the row in the Production.ProductHistory column named EndDate with tomorrow's date as well.
The tables definitions areas follows:
Production.Product:
ProductID int PK
Name varchar(50)
ProductNumber nvarchar(25)
ListPrice money
SellStartDate datetime
SellEndDate
Production.ProductListHistory:
ProductID int PK FK
StartDate datetime PK
EndDate datetime
ListPrice money
Here is what I have so far that continues to give me errors:
CREATE PROCEDURE UPDATE_AND_INSERT
(#newprice money)
AS
BEGIN
UPDATE AdventureWorks2008R2.Production.Product
SET #newprice = 25 + AdventureWorks2008R2.Production.Product.ListPrice
WHERE AdventureWorks2008R2.Production.Product.Name LIKE 'All-Purpose%'
#newprice = AdventureProduct.Production.Listprice
END
If I understood your question, Your UPDATE should be something like this
You can also create a table variable to store your deleted list price and then insert it into your history table
DECLARE #MyTableVar table(
ProductID int NOT NULL,
StartDate datetime,
EndDate datetime,
ListPrice money);
UPDATE AdventureWorks2008R2.Production.Product
Set ListPrice = 25 + AdventureWorks2008R2.Production.Product.ListPrice
OUTPUT inserted.ProductID,
inserted.SellStartDate,
inserted.SellEndDate,
deleted.ListPrice
INTO #MyTableVar
where AdventureWorks2008R2.Production.Product.Name Like 'All-Purpose%'
AND Listprice = AdventureProduct.Production.Listprice