SQL Check Constraint with User Defined Function - sql

I am troubleshooting an issue seen in our sql server database recently.
Table 1 has a calculated bit column based off of a user defined function which checks if a record exists in another table and evaluates to 0 if not.
Table 2 is the table searched by the function for Table 1. Table 2 also has a check constraint using a function to see if the bit field in Table 1 is set to 1.
This seems like a circular dependency. The problem is that when inserting a batch of records into Table 2, the constraint fails. Inserting these same records 1 by 1 allows all of the inserts to go through. I can't for the life of me figure out why batch inserts cause it to fail. Any help is appreciated.
CREATE TABLE [dbo].[tPecosPriceCheckStoreSubcategory](
[PecosPriceCheckID] [int] NOT NULL,
[StoreID] [int] NOT NULL,
[SubcategoryID] [int] NOT NULL,
[UndirectedExpectedScans] [int] NULL,
[PriceMin] [decimal](8, 2) NULL,
[PriceMax] [decimal](8, 2) NULL,
[PastPriceVariancePercent] [decimal](5, 2) NULL,
[ChangeDate] [datetime] NOT NULL,
[IsUndirected] [bit] NOT NULL,
[IsDirected] AS ([dbo].[fnPecosPriceCheckStoreSubcategoryIsDirected]([PecosPriceCheckID],[SubcategoryID])),
CONSTRAINT [PK_tPecosPriceCheckStoreSubcategory] PRIMARY KEY CLUSTERED
(
[PecosPriceCheckID] ASC,
[StoreID] ASC,
[SubcategoryID] ASC
)
ALTER TABLE [dbo].[tPecosPriceCheckStoreSubcategory] ADD CONSTRAINT [DF_IsUndirected] DEFAULT ((0)) FOR [IsUndirected]
GO
CREATE FUNCTION [dbo].[fnPecosPriceCheckStoreSubcategoryIsDirected]
(
#PecosPriceCheckID int,
#SubcategoryID int
)
RETURNS bit
AS
BEGIN
declare #isDirected bit
set #isDirected = 0
if (exists (select 1 from tPecosDirectedPriceCheckItem where PecosPriceCheckID = #PecosPriceCheckID and SubcategoryID = #SubcategoryID ))
begin
set #isDirected = 1
end
return #isDirected
END
CREATE TABLE [dbo].[tPecosDirectedPriceCheckItem](
[ID] [int] IDENTITY(1,1) NOT NULL,
[PecosPriceCheckID] [int] NOT NULL,
[PecosItemID] [int] NOT NULL,
[ItemSortOrder] [int] NOT NULL,
[SubcategoryID] [int] NOT NULL,
[ChangeDate] [datetime] NULL,
CONSTRAINT [PK_tPecosDirectedPriceCheckItem] PRIMARY KEY CLUSTERED
(
[ID] ASC
)
ALTER TABLE [dbo].[tPecosDirectedPriceCheckItem] WITH NOCHECK ADD CONSTRAINT [CK_tPecosDirectedPriceCheckItem_CheckPriceCheckSubcategoryDirected] CHECK (([dbo].[fnCheckDirectedItemPriceCheckSubcategory]([PecosPriceCheckID],[SubcategoryID])=(0)))
GO
ALTER TABLE [dbo].[tPecosDirectedPriceCheckItem] CHECK CONSTRAINT [CK_tPecosDirectedPriceCheckItem_CheckPriceCheckSubcategoryDirected]
GO
CREATE FUNCTION [dbo].[fnCheckDirectedItemPriceCheckSubcategory]
(
#PriceCheckID INT,
#SubcategoryID INT
)
RETURNS BIT
AS
BEGIN
DECLARE #isViolation BIT
SET #isViolation =
CASE WHEN EXISTS (SELECT * FROM tPecosPriceCheckStoreSubcategory WHERE SubcategoryID = #SubcategoryID AND PecosPriceCheckID = #PriceCheckID AND IsDirected = 1)
THEN
0
ELSE
1
END
RETURN #isViolation
END

Related

Filtering results between two dates with rdlc report in asp.net mvc

I am using RDLC for reports loaded into ASP.NET MVC.
I tried to filter the results between two dates, but when I type the following query below I get the following error:
"the new command text returns data with schema different from the schema of the main query. Check your query's command text if this is not desired."
Can you help me on how to do it?
SELECT
SiparisKalems.SiparisKalemId,
SiparisKalems.Siparisid,
SiparisKalems.SiparisKalemTarih,
SiparisKalems.SiparisKalemAdet,
SiparisKalems.SiparisKalemFiyat,
SiparisKalems.SiparisKalemToplam,
SiparisKalems.Urunid,
Uruns.Urunid AS Expr1,
Uruns.UrunAdi,
Uruns.UrunFiyat,
Uruns.UrunGorsel,
Uruns.Kategoriid,
Uruns.Durum
FROM
SiparisKalems
INNER JOIN Uruns ON SiparisKalems.Urunid = Uruns.Urunid
WHERE
(
SiparisKalems.SiparisKalemTarih >= #Param1
AND
SiparisKalems.SiparisKalemTarih <= #Param2
)
ORDER BY
SiparisKalems.SiparisKalemTarih DESC
CREATE TABLE [dbo].[SiparisKalems](
[SiparisKalemId] [int] NOT NULL IDENTITY(1,1),
[Siparisid] [int] NOT NULL,
[SiparisKalemTarih] [datetime] NOT NULL,
[SiparisKalemAdet] [int] NOT NULL,
[SiparisKalemFiyat] [decimal](18, 2) NOT NULL,
[SiparisKalemToplam] [decimal](18, 2) NOT NULL,
[Urunid] [int] NOT NULL,
CONSTRAINT PK_dbo.SiparisKalems PRIMARY KEY CLUSTERED ( [SiparisKalemId] ),
CONSTRAINT FK_dbo.SiparisKalems_dbo.Siparislers_Siparisid ([Siparisid]) REFERENCES [dbo].[Siparislers] ([Siparisid]) ON DELETE CASCADE,
CONSTRAINT [FK_dbo.SiparisKalems_dbo.Uruns_Urunid] FOREIGN KEY([Urunid]) REFERENCES [dbo].[Uruns] ([Urunid]) ON DELETE CASCADE
)
CREATE TABLE [dbo].[Uruns](
[Urunid] [int] NOT NULL IDENTITY(1,1),
[UrunAdi] [varchar](30) NOT NULL,
[UrunFiyat] [decimal](18, 2) NOT NULL,
[UrunGorsel] [varchar](250) NOT NULL,
[Kategoriid] [int] NOT NULL,
[Durum] [bit] NOT NULL,
CONSTRAINT [PK_dbo.Uruns] PRIMARY KEY ( [Urunid] ),
CONSTRAINT [FK_dbo.Uruns_dbo.Kategoris_Kategoriid] FOREIGN KEY([Kategoriid]) REFERENCES [dbo].[Kategoris] ([Kategoriid]) ON DELETE CASCADE
)

Audit history of sql child table

I'm recording all insert and update on TaskDetail table using a trigger,Now I want to assign multiple staff to a task, But if staff id stored in different child table how can I track audit history, I have considered storing staff id as comma separated values but child table is always a good option.
In TaskStaff table multiple staff will have same taskId
CREATE TRIGGER [dbo].[TaskDetail_History_Trigger]
ON [dbo].[TaskDetail]
FOR Insert,UPDATE
AS
INSERT INTO TaskHistory SELECT * FROM inserted
GO
ALTER TABLE [dbo].[ProductionDetail] ENABLE TRIGGER [Task_History_Trigger]
GO
CREATE TABLE [dbo].[TaskDetail](
[Id] [int] IDENTITY(1,1) NOT NULL,
[StaffId] [int] NULL,
CONSTRAINT [PK_ProductionDetail_1] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
CREATE TABLE [dbo].[TaskHistory](
[HistoryId] [int] IDENTITY(1,1) NOT NULL,
[Id] [int] NOT NULL,
[StaffId] [int] NULL,
CONSTRAINT [PK_ProductionDetail_1] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
CREATE TABLE [dbo].[TaskStaff](
[Id] [int] IDENTITY(1,1) NOT NULL,
[TaskId] [int] NOT NULL,
[StaffId] [int] NOT NULL,
CONSTRAINT [PK_ProductionDetailStaff] PRIMARY KEY CLUSTERED
(
[Id] ASC
)

SQL unique column based on other columns

I have a SQL Server database table that I am trying to fix without having to resort to using the front end code to determine if the name of the institute is unique. I am setting up a Linq to SQL code base for all of the inserts.
here is the new table that I am trying to setup:
CREATE TABLE [dbo].[institution]
(
[institutionID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[typeID] [tinyint] NOT NULL REFERENCES [dbo].[institutiontype]([institutiontypeID]),
[name] [varchar](255) NOT NULL UNIQUE,
[cityID] [int] NULL REFERENCES [dbo].[city]([cityID]),
[stateID] [int] NULL REFERENCES [dbo].[stateprovince]([stateID]),
[countryID] [int] NULL REFERENCES [dbo].[country]([countryID]),
[createby] [int] NOT NULL REFERENCES [dbo].[ipamuser]([ipamuserID]),
[createdatetime] [datetime] NOT NULL DEFAULT (GETDATE()),
[modifyby] [int] NULL REFERENCES [dbo].[ipamuser]([ipamuserID]),
[modifydatetime] [datetime] NULL,
[dataversion] [int] NOT NULL DEFAULT (0)
)
The issue is, the institutionname needs to be unique ONLY when the cityID, stateID and the countryID are the same. Setting up the table with the institutename as unique will not satisfy the needs since there are times when the same name can exist in different, cities, states or countries.
How would I resolve this
You need to write a complex constraint in your table. Define a user-defined-function which returns true (1 in BIT) if your required condition is satisfied and false otherwise.
Put this constraint in the table schema with a CHECK constraint.
CREATE FUNCTION dbo.fnIsNameUnique (
#name [varchar](255),
#cityID int,
#stateID int,
#countryID int,
)
RETURNS tinyint
AS
BEGIN
DECLARE #Result tinyint
IF EXISTS(SELECT * FROM institution WHERE name = #name AND cityID = #cityID AND stateID = #stateID AND countryID = #countryID)
SET #Result= 0
ELSE
SET #Result= 1
RETURN #Result
END
CREATE TABLE [dbo].[institution]
(
[institutionID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[typeID] [tinyint] NOT NULL REFERENCES [dbo].[institutiontype]([institutiontypeID]),
[name] [varchar](255) NOT NULL UNIQUE,
[cityID] [int] NULL REFERENCES [dbo].[city]([cityID]),
[stateID] [int] NULL REFERENCES [dbo].[stateprovince]([stateID]),
[countryID] [int] NULL REFERENCES [dbo].[country]([countryID]),
[createby] [int] NOT NULL REFERENCES [dbo].[ipamuser]([ipamuserID]),
[createdatetime] [datetime] NOT NULL DEFAULT (GETDATE()),
[modifyby] [int] NULL REFERENCES [dbo].[ipamuser]([ipamuserID]),
[modifydatetime] [datetime] NULL,
[dataversion] [int] NOT NULL DEFAULT (0),
CONSTRAINT ckValidName CHECK (
dbo.fnIsNameUnique(name, cityID, stateID, countryID) = 1)
)
)
I don't know why you need anything so complex, just putting a UNIQUE constraint or index on ([name], CityID, StateID, CountryID) does what you say you need.

update trigger to update records in another table

I have on User_Table
CREATE TABLE [dbo].[User_TB]
(
[User_Id] [varchar](15) NOT NULL,
[User_FullName] [varchar](50) NULL,
[User_Address] [varchar](150) NULL,
[User_Gender] [varchar](10) NULL,
[User_Joindate] [varchar](50) NULL,
[User_Email] [varchar](50) NULL,
[User_Branch] [varchar](50) NULL,
[User_TeamLeader] [varchar](50) NULL,
[User_Department] [varchar](50) NULL,
[User_Position] [varchar](50) NULL,
[TID] [int] NULL
)
Break_Table
CREATE TABLE [dbo].[Break_TB]
(
[Break_Id] [int] IDENTITY(1,1) NOT NULL,
[User_Id] [varchar](15) NOT NULL,
[Date] [date] NULL,
[Break_Time] [int] NULL,
[Status] [varchar](50) NULL,
[Late_time] [int] NULL,
[TL_Id] [varchar](15) NULL,
[start_Time] [time](7) NULL,
[end_Time] [time](7) NULL,
)
Log_Table
CREATE TABLE [dbo].[Log_TB]
(
[User_Id] [varchar](50) NOT NULL,
[First_Login] [time](0) NULL,
[Logout] [time](0) NULL,
[Date] [date] NULL,
[Working_Hrs] [time](0) NULL,
)
Now what am trying to do is that whenever the User_Id from User_Table is Updated , I want trying to update User_Id of Another two tables,
I have written trigger for that
Alter TRIGGER [dbo].[updateUserId] on [dbo].[User_TB]
FOR Update
AS
declare #Branch_Name varchar(50),
#User_Id varchar(15)
select #User_Id = i.User_Id from inserted i;
Update Break_TB set User_Id = #User_Id where User_Id = #User_Id;
Update Log_TB set User_Id = #User_Id where User_Id = #User_Id;
But
It only updates records from Break_TB, It not works for Log_TB
Am not very good at triggers, if am wrong please Help me.
You would need something like this - a set-based solution that takes into account that in an UPDATE statement, you might be updating multiple rows at once, and therefore your trigger also must deal with multiple rows in the Inserted and Deleted tables.
CREATE TRIGGER [dbo].[updateUserId]
ON [dbo].[User_TB]
FOR UPDATE
AS
-- update the "Break" table - find the rows based on the *old* User_Id
-- from the "Deleted" pseudo table, and set it to the *new* User_Id
-- from the "Inserted" pseudo table
SET User_Id = i.User_Id
FROM Inserted i
INNER JOIN Deleted d ON i.TID = d.TID
WHERE
Break_TB.User_Id = d.User_Id
-- update the "Log" table - find the rows based on the *old* User_Id
-- from the "Deleted" pseudo table, and set it to the *new* User_Id
-- from the "Inserted" pseudo table
UPDATE Break_TB
SET User_Id = i.User_Id
FROM Inserted i
INNER JOIN Deleted d ON i.TID = d.TID
WHERE
Break_TB.User_Id = d.User_Id
This code assumes that the TID column in the User_TB table is the primary key which remains the same during updates (so that I can join together the "old" values from the Deleted pseudo table with the "new" values after the update, stored in the Inserted pseudo table)

How to create a trigger to modify date column on table with double key

I need to create a trigger that saves the current date&timestamp into the row when it is being inserted or updated.
Table structure
[Period] [char](7) NOT NULL,
[CompanyAlfaCode] [char](2) NOT NULL,
[SamplePercentaje] [int] NULL,
[Usuario] [varchar](50) NULL,
[Date] [Datetime] NULL,
Thank you very much.
Maybe something like:
CREATE TRIGGER DateTrigger ON CompanySampleConfig
AFTER INSERT,UPDATE
AS
BEGIN
UPDATE CompanySampleConfig SET [Date] = current_timestamp
WHERE EXISTS
(SELECT '' FROM inserted
WHERE CompanySampleConfig.[Period] = inserted.[Period]
AND CompanySampleConfig.[CompanyAlfaCode] = inserted.[CompanyAlfaCode]
END