Stored Procedure to Cascade Delete Customer? - c#

I have a project to implement a form which inserts, updates, and deletes Customers from Northwind -> Customers. I managed to do Insertion, Update, and refresh it after every operation, but delete won't work and throws FK exceptions. I need to cascade on delete, but I don't know how..
My form looks like this :
and my procedure for delete (so far, no cascade) :
CREATE Procedure [dbo].[DeleteCustomer]
(
#Original_CustomerID nchar(5)
)
AS
SET NOCOUNT OFF;
DELETE FROM [dbo].[Customers]
WHERE
(
(
[CustomerID] = #Original_CustomerID
)
)
which works in some cases, but in others I get an error :
The DELETE statement conflicted with the REFERENCE constraint "FK_Orders_Customers". The conflict occurred in database "Northwind",
table "dbo.Orders", column 'CustomerID'. The statement has been
terminated.
Can anyone help me finish this project by adding cascade on delete?
It's Northwind Traders database, Customer table.

One easy way to handle this is to drop and readd the constraint as a cascading delete constraint in SQL Enterprise Manager (or the ISQLW interpreter of your choice):
USE Northwind
GO
ALTER TABLE Orders
DROP CONSTRAINT
FK_Orders_Customers
GO
ALTER TABLE Orders
ADD
CONSTRAINT FK_Orders_Customers FOREIGN KEY
(
CustomerID
) REFERENCES Customers
CustomerID
) ON CASCADE DELETE
GO
If you want to have a strictly stored procedure solution, you can use this revision of your original stored procedure:
CREATE Procedure [dbo].[DeleteCustomer] (
#Original_CustomerID nchar(5)
)
AS
SET NOCOUNT OFF;
DELETE
FROM [dbo].[Orders]
WHERE [CustomerID] = #Original_CustomerID
DELETE
FROM [dbo].[Customers]
WHERE [CustomerID] = #Original_CustomerID

Where do I put your code? Do I save/run as a stored procedure?
It still throws the exception.. :/
My delete :
private void buttonDelete_Click(object sender, RoutedEventArgs e)
{
SqlConnection cn = new SqlConnection(#"Integrated Security=SSPI;Initial Catalog=Northwind;Data Source=(local)");
SqlCommand cmd = new SqlCommand("DeleteCustomer", cn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Original_CustomerID", textBox_CompanyID.Text);
cn.Open();
cmd.ExecuteNonQuery();
cn.Close();
lbxCustomers.Items.Clear();
this.init();
}
My DeleteCustomer procedure :
CREATE Procedure [dbo].[DeleteCustomer]
(
#Original_CustomerID nchar(5)
)
AS
SET NOCOUNT OFF;
DELETE FROM [dbo].[Customers]
WHERE
(
(
[CustomerID] = #Original_CustomerID
)
)
And I have your code, but don't know how to add it to my project to make it work. So when I restart application or switch computer it would still work. Help please.. I think it's new error. There are 3 tables connected as it seems :
The DELETE statement conflicted with the REFERENCE constraint "FK_Order_Details_Orders". The conflict occurred in database "Northwind", table "dbo.Order Details", column 'OrderID'.
The statement has been terminated.

Related

Dealing with DelteBehavior.Restrict when syncing data between two databases

We need to keep a specific table in sync between two databases. For this there is a background job in-place. The process is that EF core
queries all the table data in db1
maps the data into EF Core entities for db2
clears the existing rows in the table in db2 and finally
inserts the mapped entities into the table in db2
However, the table has relationships to other tables in db2. These reference to it via foreign keys. The FK's DeleteBehavior enum is set to Restrict.
Therefore, when in step #3 the existing records are to be deleted, there is an exception, since there are depending entities in other tables.
To work around this problem, the following procedure is invoked, temporarily disabling all the relationships constraints. Afterwards, meaning after deletion and re-insertion of the records, this is reversed.
This works fine, however I find this incredibly ugly. What are your takes on this? Can somebody make a better proposal? 🙌
Any advice or suggestions are greatly appreciated!
Here's the stored procedure to disable the FK constraints (source here)
DROP PROCEDURE [schema].[disableFks]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [schema].[disableFks]
AS
DECLARE #sql NVARCHAR(MAX) = N'';
with SCH as
(
select SCHEMA_ID from sys.schemas where name in ('sch1', 'sch2', 'sch3')
)
, FKS AS
(
SELECT DISTINCT obj = QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.' + QUOTENAME(OBJECT_NAME(parent_object_id))
FROM sys.foreign_keys
WHERE sys.foreign_keys.schema_id in (select schema_id from SCH)
)
SELECT #sql += N'ALTER TABLE ' + obj + ' NOCHECK CONSTRAINT ALL;' FROM FKS;
EXEC sp_executesql #sql;
GO

Incorrect syntax near the keyword 'if' SQL Command [duplicate]

I want to make SQL Server script for creating database if it does not exist.
IF NOT EXISTS(SELECT * FROM sys.databases WHERE name = 'DataBase')
BEGIN
CREATE DATABASE DataBase
USE DataBase
CREATE TABLE TableName (
Id INT PRIMARY KEY IDENTITY (1, 1),
Name VARCHAR(100)
)
--more tables here
--some procedures here too
END
From code above I'm getting this error:
Msg 911, Level 16, State 1, Line 5
Database 'DataBase' does not exist. Make sure that the name is entered correctly.
How to make database with tables and procedures when database does not exist? I want to make it in one query.
Could you check the following script :
IF NOT EXISTS(SELECT * FROM sys.databases WHERE name = 'DataBase')
BEGIN
CREATE DATABASE [DataBase]
END
GO
USE [DataBase]
GO
--You need to check if the table exists
IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='TableName' and xtype='U')
BEGIN
CREATE TABLE TableName (
Id INT PRIMARY KEY IDENTITY (1, 1),
Name VARCHAR(100)
)
END
Obviously you have to start with (and mind the GO here):
USE master
GO
But you have to do it like this:
IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = 'MyTestDataBase')
BEGIN
CREATE DATABASE MyTestDataBase;
END;
GO
Mind the GO again. If you don't use GO SSMS (or any other client) will still think your batch is not completed, your database is still not created and therefore not available for further use, and you get the error message you posted.
Now you can start using your just created database with:
USE MyTestDataBase;
GO
Again, mind the GO statement. In this case it is inadmissible because it is not possible to combine CREATE DATABASE and CREATE TABLE statements in one batch. So after the GO continue with:
IF OBJECT_ID('MyTestTable', 'U') IS NULL
BEGIN
CREATE TABLE dbo.MyTestTable
(
Id INT PRIMARY KEY IDENTITY(1, 1)
, Name VARCHAR(100)
);
END;
As already mentioned by others it is good practice to check if every table exists and do a create action if it doesn't and alter action if it does (or just do nothing). But if you really don't want to check if each table exists, for instance when you are sure you need to start from scratch, you could start with dropping the database if it exists:
IF EXISTS (SELECT * FROM sys.databases WHERE name = 'MyTestDataBase')
BEGIN
DROP DATABASE MyTestDataBase;
END;
CREATE DATABASE MyTestDataBase;
GO
You can try this.
IF NOT EXISTS (
SELECT *
FROM sys.databases
WHERE name = 'DataBase'
)
BEGIN
CREATE DATABASE [DataBase]
END
GO
USE [DataBase]
GO
IF NOT EXISTS (
SELECT 1
FROM sys.tables
WHERE name = 'TableName'
AND type = 'U'
)
BEGIN
CREATE TABLE TableName (
Id INT PRIMARY KEY IDENTITY(1, 1)
,Name VARCHAR(100)
)
END

The INSERT statement conflicted with the FOREIGN KEY constraint "FK_

I have two tables , one to one relationship i makes DetailsID of projectDetails FK in ID of projects table:
projects:
ID, //has FK With DetailsID in Details table & auto identity (1,1)
ProjectName,
Areas,
PaymentSystem,
ReceivedDate,
PropertyClassification,
ProjectImage
ProjectDetails:
DetailsID ,auto identity ( 1,1)
ProjectDetailName,
ProjectDetailImage
I am trying to insert new record in projects table , gives me this error at this line of code :
con.Open();
comm.ExecuteNonQuery(); // when execute
System.Data.SqlClient.SqlException: 'The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Projects_ProjectDetails". The conflict occurred in database "AlamaarRealEstate", table "dbo.ProjectDetails", column 'DetailsID'.
and this is my stored to insert :
ALTER proc [Insert_Project]
#Projectname NVARCHAR(MAX) ,
#areas NVARCHAR(MAX) ,
#Paymentsystem NVARCHAR(MAX) ,
#Receiveddate date ,
#Classification NVARCHAR(MAX) ,
#Projectimage Nvarchar(MAX)
as
INSERT INTO dbo.Projects
(
ProjectName,
Areas,
PaymentSystem,
ReceivedDate,
PropertyClassification,
ProjectImage
)
VALUES
(
#Projectname ,
#areas,
#Paymentsystem ,
#Receiveddate ,
#Classification,
#Projectimage
)
The question explains the answer. Referential Integrity is not maintained properly, you are trying to insert into a child table for which the master value does not exist. Please insert values to Project_details first. This will resolve your issue. If you did not what this to throw an error, just check the existence of the DetailID in Projects table before inserting.
Without more detail your question is hard to answer. For instance in your procedure you do explicit column naming for inserts and LEAVE OUT the column you are having a problem with. So if the proc was wrong it would be bombing with your example foreign key constraint error. But you are not even listing the 'ID' field to insert into with the procedure. So this is common if you are using an 'Identity' field to self seed, but you are claiming it is a foreign key. So like others have commented, without more code to show the exact way your tables are made it's hard to guess. Here is a self extracting example you could run that shows if a column is nullable and I had a key constraint it would work. Without the exact code of the tables as well as the proc it is hard to tell. What you gave is pseudo code.
USE Tester --just a test database I have, you can use whatever database you want
GO
IF OBJECT_ID('Projects') IS NOT NULL
DROP TABLE Projects
IF OBJECT_ID('ProjectDetails') IS NOT NULL
DROP TABLE ProjectDetails
create TABLE ProjectDetails
(
DetailsID INT CONSTRAINT PK_DetailsId PRIMARY KEY,
ProjectDetailName VARCHAR(32)
)
CREATE TABLE Projects
(
Id INT CONSTRAINT FK_Projects_ProjectDetails FOREIGN KEY (Id) REFERENCES ProjectDetails(DetailsId),
ProjectName varchar(32)
)
GO
IF OBJECT_ID('Insert_Project') IS NOT NULL
DROP PROC Insert_Project
GO
Create proc Insert_Project
#Projectname NVARCHAR(MAX)
as
INSERT INTO dbo.Projects ( ProjectName )
VALUES ( #Projectname )
GO
Select *
From dbo.Projects
EXEC dbo.Insert_Project #Projectname = N'Test' -- nvarchar(max)
Select *
From dbo.Projects

Stored Procedure with IsIDenity and cmd.Parameters.Add

I am creating an ASP.NET Wiki for myself to track the knowlege I gain in C# and other language.
I have created a Stored Procedure to insert a category into a DB, the DB has two fields C_ID(int) and Category(varchar 25). In my ASP page, there is no field for C_ID, it increments automatically by IsIdentiy = true;
When I try to excute it, it fails. What is the best approach to handle this?
Code:
ALTER PROCEDURE dbo.InsertCategory
#ID int,
#CATEGORY varchar(25)
AS
INSERT INTO Wiki
(C_ID, C_Category)
Values (#ID, #CATEGORY)
/* SET NOCOUNT ON */
RETURN
Did I miss something to insert from the .aspx page?
try
{
//create a command object identifying the Stored Procedure
SqlCommand cmd = new SqlCommand("InsertCategory", conn);
//Set the command type
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("Category", txtAddCatagory));
cmd.ExecuteNonQuery();
}
Just omit the id from the insert. If you configured identity correctly, the database will take care of increasing the number. For example:
GO
ALTER PROCEDURE dbo.InsertCategory(#CATEGORY varchar(25))
AS
INSERT INTO Wiki (C_Category) Values (#CATEGORY)
GO
To verify the identity is set correctly, if you script the table, the C_id column should look like;
[C_id] [int] IDENTITY(1,1) NOT NULL,
Or even better:
[C_id] [int] IDENTITY(1,1) PRIMARY KEY,
So you're getting an exception that you cannot insert into an identity column, right? The trick is to not specify the identity column in your insert statement, because it automatically get populated... ;)
ALTER PROCEDURE dbo.InsertCategory #CATEGORY varchar(25) AS
INSERT INTO Wiki (C_Category) Values (#CATEGORY) /* SET NOCOUNT ON */ RETURN

deadlock when SQL Server transaction log ever-increase?

I am using SQL Server 2008 Enterprise. I have tried that if I set SQL Server transaction log to ever increase for the related database (with no backup settings), then a single delete statement of this stored procedure will cause deadlock if executed by multiple threads at the same time? Any ideas why?
For the delete statement, Param1 is a column of table FooTable, Param1 is a foreign key of another table (refers to another primary key clustered index column of the other table). There is no index on Param1 itself for table FooTable. FooTable has another column which is used as clustered primary key, but not Param1 column.
create PROCEDURE [dbo].[FooProc]
(
#Param1 int
,#Param2 int
,#Param3 int
)
AS
DELETE FooTable WHERE Param1 = #Param1
INSERT INTO FooTable
(
Param1
,Param2
,Param3
)
VALUES
(
#Param1
,#Param2
,#Param3
)
DECLARE #ID bigint
SET #ID = ISNULL(##Identity,-1)
IF #ID > 0
BEGIN
SELECT IdentityStr FROM FooTable WHERE ID = #ID
END
As a rule of thumb, you should always create an index on the column that has FOREIGN KEY constraint. Otherwise, deadlock is very likely to happen (because the server has to lock the whole dependent table to ensure that constraint)

Categories