deadlock when SQL Server transaction log ever-increase? - c#

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)

Related

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

T-SQL insert into sometimes fails to add to a table at random

So I have two tables, Records (Input ID = Primary Key) and TaskNotes (Input Id, TaskNote : No primary key).
There used to be a single stored procedure which would add to the record table, get the primary id that was generated, then add that ID to the TaskNotes table, along with the task notes text.
Recently, there was an issue where the sproc would run seemingly half way, with the record being added, but the task notes entry not being run.
I since split out into an AddRecord stored procedure and an AddTaskNotes stored procedure, which are being called from a C# application.
This works as similarly as before, however, at random the AddTaskNotes still wont be run.
I think the issue is a locking of the TaskNotes table.
Has anyone experienced this before and could let me know how it was resolved?
The current rate is about 1 failed tasknotes for every 400 record entries.
This is the AddRecord statement;
INSERT INTO Time.Records
( TeamID ,
UserID ,
TimeIN ,
TimeOUT
)
VALUES ( #TeamID , #UserID , #TimeIN , #TimeOUT );
return SCOPE_IDENTITY();
This is the AddTaskNotes statement;
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
INSERT INTO Time.TaskNotes ( InputID, TaskNotes )
VALUES ( #InputID, #TaskNotes );
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

How to set a column equal to the Primary key?

How can I get the primary key value and put it in another column when I insert the data?
Here is my table schema:
CREATE TABLE IF NOT EXISTS [MyTable] (
[ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[custom_ID] INTEGER NULL,
[Name] VARCHAR (200) NULL)
The query I have so far is:
INSERT INTO MyTable (custom_ID, Name)
values (
' {Here I need to get the primary key value, and then put it in custom_ID} ',
'someName')
Thanks!
Don't do that. You are violating all sorts of good database design principles by going this route. The primary key is supposed to represent the data that unique identifies a tuple (row). When you start having multiple copies of your primary key, you in turn defeat the entire purpose of the key.
As suggested by Chris:
CREATE TRIGGER MyTable_CustomID AFTER INSERT ON MyTable WHEN NEW.Custom_ID=NULL BEGIN
UPDATE MyTable SET Custom_ID=NEW.Id WHERE ROWID=NEW.ROWID;
END;
As far I can say you are trying to generate some custom Id based upon the PK. Like if my PK = 1 then you need a custom Id as ABCDEF/000/1 . So in that case you have to pick the immediate Id generate by the insert query and then run a update statement either in a trigger or just after the insert statement. Since its sql lite so you need to research a little bit to get identity similar to Scope_Identity() or ##Identity in Sql Server.
Try something like this:
insert [Order] (col1, col2, ...) values ('val1', 'val2', ...) -- Note: no ID is specified
declare #id int = scope_identity()
insert OrderDetail (order_id, col1, ...) values (#id, 'val1', ...)

Stored Procedure to Cascade Delete Customer?

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.

Categories