I have a table where the rows are duplicated. I would like to remove the duplicates and add a Composite Key to avoid duplicates.
;WITH myCTE (RowNumber, invoice_id, Invoice_Number, Organization_id, status, created_at) AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY Invoice_Number ORDER BY invoice_id, Invoice_Number DESC) AS RowNumber ,
invoice_id, Invoice_Number, Organization_id,status, created_at
FROM
Invoice_Export
)
SELECT *
FROM myCTE
WHERE Invoice_number LIKE '%-00%'
ORDER BY invoice_id
select * from Invoice_Export
ALTER TABLE Invoice_Export ALTER COLUMN [Organization_id] NVARCHAR(36) NOT NULL
ALTER TABLE Invoice_Export ALTER COLUMN [Invoice_Number] NVARCHAR(15) NOT NULL
ALTER table Invoice_Export
ADD CONSTRAINT [Composite_Key_Invoice] PRIMARY KEY CLUSTERED (Organization_id, Invoice_Number)
Is there any other better approach for the same.
I'm guessing that 'invoice_id' is unique, so
DELETE FROM Invoice_Export duplicate
WHERE EXISTS (SELECT 1 FROM Invoice_Export
WHERE duplicate.invoice_id > Invoice_Export.invoice_id
AND duplicate.Organization_id = Invoice_Export.Organization_id
AND duplicate.Invoice_Number = Invoice_Export.Invoice_Number)
instead PRIMARY KEY you can use UNIQUE (after removing duplicates)
ALTER TABLE Invoice_Export
ADD CONSTRAINT UC_Invoice_Export UNIQUE (Organization_id, Invoice_Number);
Related
I am trying to create a trigger where it filters the itemID first and then checks the most highest bidNo of that itemID. bidNo has to be only +1 bigger than the last. bid is bidder.
CREATE TRIGGER new_bid_no
BEFORE INSERT ON BID
BEGIN
SELECT CASE
WHEN (SELECT itemID
FROM bid
WHERE itemID = NEW.itemID
GROUP BY itemID
) AND (SELECT MAX(bidNo) AS bidNo
FROM bid
WHERE NEW.bidNo < bidNo
OR NEW.bidNo = (bidNo+1)
GROUP BY itemID
)THEN
RAISE (ABORT, 'New bid number has to be 1 higher than the last')
END;
END;
the bid table
CREATE TABLE BID(
buyerUsername VARCHAR(30) NOT NULL,
itemID INTEGER NOT NULL,
bidNo INTEGER NOT NULL,
bidAmount INTEGER,
bidDate VARCHAR(10),
bidTime TIME,
PRIMARY KEY(buyerUsername, itemID, bidNo),
FOREIGN KEY (buyerUsername) REFERENCES BUYER(buyerUsername),
FOREIGN KEY (itemID) REFERENCES ITEM(itemID)
)
WITHOUT ROWID;
First, you must define a UNIQUE constraint for itemID, bidNo and this can be done only in the CREATE statement of the table and not added later:
CREATE TABLE BID(
buyerUsername TEXT NOT NULL,
itemID INTEGER NOT NULL,
bidNo INTEGER NOT NULL,
bidAmount INTEGER,
bidDate TEXT,
bidTime TEXT,
PRIMARY KEY(buyerUsername, itemID, bidNo),
FOREIGN KEY(buyerUsername) REFERENCES BUYER(buyerUsername),
FOREIGN KEY(itemID) REFERENCES ITEM(itemID),
UNIQUE(itemID, bidNo)
)
WITHOUT ROWID;
I also changed the data types of the columns that you defined as VARCHAR to TEXT, because there is no VARCHAR data type in SQLite. Even if you defined it as such it will be TEXT. Also there is no data type TIME.
Now your trigger can be written like this:
CREATE TRIGGER new_bid_no
BEFORE INSERT ON BID
WHEN NEW.bidNo <> COALESCE((SELECT MAX(bidNo) FROM bid WHERE itemID = NEW.ItemID AND bidNo < NEW.bidNo), 0) + 1
BEGIN
SELECT RAISE (ABORT, 'New bid number has to be 1 higher than the last');
END
I am trying to insert all the rows of cart Table of userId=1 into Order and OrderItem table the Order table consists of following columns:
ORDER TABLE
1.OrderId (int)
2.OrderDate(datetime)
3.userId (int)
4.orderStatus (varchar)
the user_tbltable is reference to the Order table with PK of userId and
cart table is also reference with userId
CART TABLE
Id
userId
Quantity
productID
ORDERITEM TABLE
id
orderid
productid
qty
ITEM Table
ProductId
Name
SizeId
ColorId
Price
Imageurl
I have tried following but this giving me conflict error:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_OrderItem_Item". The conflict occurred in database "db", table "dbo.Item", column 'Id'
insert into [Order] values(getdate(),#userId,#status);
set #orderId = ##IDENTITY
insert into OrderItem (OrderId ,ItemID,Qty,ColorId,SizeId)
select #orderId,Cart.ProductId,cart.Quantity,cart.ColorId,cart.SizeId
from [Cart]
where UserId=#userId ;
Change your Query as Below
INSERT INTO [Order]
VALUES
(
GETDATE(),
#userId,
#status
);
SELECT #orderId = SCOPE_IDENTITY();--Use SCOPE_IDENTITY Instead of ##IDENTITY
INSERT INTO OrderItem
(
OrderId,
ItemID,
Qty,
ColorId,
SizeId
)
SELECT [Order].OrderId,
Cart.ProductId,
cart.Quantity,
cart.ColorId,
cart.SizeId
FROM [Cart]
INNER JOIN [Order]
ON [Cart].UserId = #userId
AND [Order].OrderId = #orderId;--SELECT Order Id From Order to be more safer
I am trying to learn SQL, and while my journey has been quite successful this far, I have run into problems with triggers. For the record, I am using SQL Server 2016. I would appreciate any help I can get. Please let me know if more details are needed.
Hope it will help
-------------
--cascade delete way
-------------
CREATE TABLE dbo.customers (
customer_id INT NOT NULL
, somedata UNIQUEIDENTIFIER NOT NULL
, CONSTRAINT PK_Customer PRIMARY KEY (customer_id)
);
CREATE TABLE dbo.orders (
OrderID INT NOT NULL
, customer_id INT NOT NULL
, somedata UNIQUEIDENTIFIER NOT NULL
, CONSTRAINT PK_Order PRIMARY KEY (OrderID)
, CONSTRAINT FK_CustomerOrder FOREIGN KEY (customer_id)
REFERENCES dbo.customers (customer_id) ON DELETE CASCADE
);
INSERT INTO dbo.customers (customer_id,somedata)
VALUES (1,NEWID()),(2,NEWID())
INSERT INTO dbo.orders(OrderID,customer_id,somedata)
VALUES (1,1,NEWID()),(2,2,NEWID())
DELETE FROM dbo.customers WHERE customer_id = 1
SELECT * FROM dbo.orders
-------------
--trigger way
-------------
CREATE TABLE dbo.customers1 (
customer_id INT NOT NULL
, somedata UNIQUEIDENTIFIER NOT NULL
, CONSTRAINT PK_Customer1 PRIMARY KEY (customer_id)
);
CREATE TABLE dbo.orders1 (
OrderID INT NOT NULL
, customer_id INT NOT NULL
, somedata UNIQUEIDENTIFIER NOT NULL
, CONSTRAINT PK_Order1 PRIMARY KEY (OrderID)
, CONSTRAINT FK_CustomerOrder1 FOREIGN KEY (customer_id)
REFERENCES dbo.customers1 (customer_id) ON DELETE CASCADE
);
GO
CREATE TRIGGER DELTRIG
ON dbo.customers1
FOR DELETE
AS
DELETE C
FROM dbo.orders1 AS C
INNER JOIN DELETED ON
C.customer_id = DELETED.customer_id
GO
INSERT INTO dbo.customers1 (customer_id,somedata)
VALUES (1,NEWID()),(2,NEWID())
INSERT INTO dbo.orders1(OrderID,customer_id,somedata)
VALUES (1,1,NEWID()),(2,2,NEWID())
DELETE FROM dbo.customers1 WHERE customer_id = 1
SELECT * FROM dbo.orders1
It is much safer if you would simply add a deleted flag in your customer table and in your trigger just update the deleted column to true.
But if you really need to delete the child records after the parent record is deleted, try using the cascade delete. You can refer from to this old post.
How do I use cascade delete with SQL Server?
Hopefully someone can help. I have created two tables Customer and Order as follows;
CREATE TABLE Customer
CustomerID int NOT NULL PRIMARY KEY
CustomerName varchar(25)
The other columns in Customer table are not relevant to my question, so I will not include them here. My CustomerID numbers are from 1 through to 15, all unique.
The second table I created is Orders as follows
CREATE TABLE Orders
OrderID smallint NOT NULL PRIMARY KEY
OrderDate date NOT NULL
CustomerID int FOREIGN KEY REFERENCES Customer (CustomerID);
My insert values is as follows
INSERT INTO Orders (OrderID, OrderDate, CustomerID)
VALUES
(1001, '2008-10-21', 1),
(1002, '2008-10-21', 8),
(1003, '2008-10-22', 15),
(1004, '2008-10-22', 5),
(1005, '2008-10-24', 3),
(1006, '2008-10-24', 2),
(1007, '2008-10-27', 11),
(1008, '2008-10-30', 12),
(1009, '2008-11-05', 4),
(1010, '2008-11-05', 1);
When I try to insert my values into the Order table, I get the following error message....
Msg 547, Level 16, State 0, Line 1.....The INSERT statement conflicted
with the FOREIGN KEY constraint "FK__OrderT__Customer__2D27B809". The
conflict occurred table "dbo.Customer", column 'CustomerID'. The
statement has been terminated.
The numbers for CustomerID in my Order table, are (1; 1; 2; 3; 4; 5; 8; 11; 12 and 15). Therefore I have checked that all my CustomerID numbers in Order table are also in the Customer table.
So my questions are
1) Has the insert values failed because my CustomerID column in Customer table in NOT NULL and I in error made CustomerID column NULL in Order.
2) If the answer to the above question is yes, then is it possible for me to (a) drop the foreign key on the CustomerID column in Order (b) change the column to NOT NULL and (c) then add the foreign key constraint again to this column and then insert the values again?
It might be easier to drop and re-create the table Order. But I am curious if option 2 would work, re dropping and adding a foreign key on the same column.
Hopefully I am on the right track with why I think the error occurred, feel
to correct me if I am wrong.
Thanks everyone
Josie
1) It should be NOT NULL in both. However error is because you attempted to insert a CustomerId that is not in Customer table.
2) You can simply alter the table and make it NOT NULL (error was not that).
Sample:
CREATE TABLE Customer
(
CustomerID INT NOT NULL
PRIMARY KEY ,
CustomerName VARCHAR(25)
);
CREATE TABLE Orders
(
OrderID INT NOT NULL
PRIMARY KEY ,
OrderDate DATE NOT NULL ,
CustomerID INT FOREIGN KEY REFERENCES Customer ( CustomerID )
);
INSERT [Customer] ( [CustomerID], [CustomerName] )
VALUES ( 1, 'Customer 1' ),
( 2, 'Customer 2' ),
( 3, 'Customer 3' ),
( 4, 'Customer 4' ),
( 5, 'Customer 5' ),
( 6, 'Customer 6' );
INSERT [Orders] ( [OrderID], [OrderDate], [CustomerID] )
VALUES
( 1, GETDATE(), 1 ),
( 2, GETDATE(), 2 ),
( 3, GETDATE(), 3 ),
( 4, GETDATE(), 4 ),
( 5, GETDATE(), 5 ),
( 6, GETDATE(), 6 );
INSERT [Orders] ( [OrderID], [OrderDate], [CustomerID] )
VALUES ( 7, GETDATE(), 7 );
Last one would error, because Customer with CustomerID 7 doesn't exist.
Update: I later saw your sample insert. You can find the offending ID like this:
DECLARE #ids TABLE ( id INT );
INSERT #ids ( [id] )
VALUES ( 1 ),
( 8 ),
( 15 ),
( 5 ),
( 3 ),
( 2 ),
( 11 ),
( 12 ),
( 4 ),
( 1 );
SELECT *
FROM #ids AS [i]
WHERE id NOT IN ( SELECT CustomerID
FROM [Customer] AS [c] );
1) Has the insert values failed because my CustomerID column in
Customer table in NOT NULL and I in error made CustomerID column NULL
in Order.
No. The error is not related to allowing NULL in the Order table. A NULL value will be allowed and not checked for referential integrity.
The foreign key violation error means you are attempting to insert a non-NULL CustomerID value into the Order table that does not exist in Customer. If you are certain the CustomerID values exist, perhaps the column mapping is wrong. Try specifying an explicit column list on the INSERT statement.
This error happens whern you are trying to insert a value in foreign key column, which this value does not exists in it's parent table. for example you are trying to insert value X to CustomerId in Order table, which this value does not exists in Customer table. This error occurred because we need to have a good strategy for Referential Integrity. So the only you need to do, is to check your new values(which you are going to insert them into table) to find out that is there any value compromising this rule or not.
However if you want to get an answer for your second question, you can try the below script:
create table t1
(
Id int primary key,
Name varchar(50) null
)
create table t2
(
Id int,
FK int null foreign key references t1(id)
)
go
alter table t2
alter column FK int not null
The identity column is set up once when you create the table.
The id assigned by an identity column start by the seed and are never reused.
So if you find that your customer ids starts from 6, it means that in the past you have added 5 customers and removed it.
If, for any reason, you want to use fixed Id don't use identity. In that case you take full responsability to set a unique value.
I suggest to never rely on fixed ids, if you must add orders from a script use the CustomerName (if unique), or any natural unique key.
You could use a script like this
DECLARE #newOrders TABLE (OrderID INT, CustomerName VARCHAR(25), OrderDate DATE);
INSERT INTO #newOrders (OrderID, CustomerName, OrderDate) VALUES
(1001, 'some-username', '2008-10-21'),
(1002, 'another-username', '2008-10-21');
INSERT INTO Orders(OrderID, CustomerId, OrderDate)
SELECT
o.OrderID,
c.CustomerID,
o.OrderDate
FROM #newOrders o
JOIN Customer c
ON c.CustomerName = o.CustomerName;
In this way you insert the correct CustomerID.
Note that in very rare cases (think twice to use it) you could insert values in identity colums using SET IDENTITY_INSERT statement.
I have a table with 10 columns but only care about 3 columns for this. Imagine my table looks like this:
CREATE TABLE MyTable ( RowID int IDENTITY(1,1), UserID int, NodeID int, RoleID int )
What I need is a constraint that enforces the following: UserID and RoleID need to be unique for each NodeID (i.e. a user cannot have the same role in multiple nodes). In other words I want to allow
INSERT MyTable (UserID, NodeID, RoleID) SELECT 1, 1, 1
but not allow
INSERT MyTable (UserID, NodeID, RoleID) SELECT 1, 2, 1
if the first insert has occurred because that would result in a user having a role in multiple nodes.
Hopefully this is simple and I'm just making it more complex than it needs to be in my brain.
Since your constraint depends on data in other rows, this rules out a filtered index. IMO a viable option could be a trigger. Such a trigger could look like something like this:
CREATE TRIGGER dbo.MyTrigger ON dbo.Q1
AFTER INSERT, UPDATE
AS
DECLARE #userId INT, #Id INT, #roleId INT, #exists INT;
SELECT TOP 1
#userId = userID
,#roleId = roleID
,#Id = Id
FROM inserted;
SELECT TOP 1
#exists = Id
FROM Q1
WHERE userId = #userId
AND roleID = #roleID AND Id<> #Id;
IF ISNULL(#exists, 0) > 0
BEGIN
-- you would want to either undo the action here when you use an 'after' trigger
-- because as the name implies ... the after means the record is allready inserted/updated
RAISERROR ('No way we would allow this.', 16, 1);
END
-- else
-- begin
-- another alternative would be to use a instead of trigger, which means the record
-- has not been inserted or updated and since that type of trigger runs the trigger 'instead of'
-- updating or inserting the record you would need to do that yourself. Pick your poison ...
-- end
GO
An unique index should enforce your requirements
CREATE UNIQUE NONCLUSTERED INDEX [idx_Unique] ON [dbo].[MyTable]
(
[UserID] ASC,
[NodeID] ASC,
[RoleID] ASC
)
From the comments I suppose you will need two unique indices
CREATE UNIQUE NONCLUSTERED INDEX [idx_User_Node] ON [dbo].[MyTable]
(
[UserID] ASC,
[NodeID] ASC
)
GO
CREATE UNIQUE NONCLUSTERED INDEX [idx_User_Role] ON [dbo].[MyTable]
(
[UserID] ASC,
[RoleID] ASC
)