I have a customized application in my company where I can create a place for users to input their values to a database.
The table where I am submitting the data has 5 columns with its SQL CREATE Query as below:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Log_Ongoing](
[ID] [int] IDENTITY(1,1) NOT NULL,
[LogType] [int] NULL,
[ActivityDate] [datetime] NOT NULL,
[ActivityDescription] [text] NULL,
[Train] [int] NULL,
CONSTRAINT [PK_Log_Ongoing] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[Log_Ongoing] WITH CHECK ADD CONSTRAINT [FK_Log_Ongoing_Trains] FOREIGN KEY([Train])
REFERENCES [dbo].[Trains] ([Id])
GO
ALTER TABLE [dbo].[Log_Ongoing] CHECK CONSTRAINT [FK_Log_Ongoing_Trains]
GO
The purpose of this table is to record the ongoing activities in the plant.
The user can come later and modify those activities by updating, adding or deleting through the application by choosing the report data then modifying the data.
My thinking was that before the user submits the data I will delete the old data with the same report date first then insert the new data again.
Unfortunately the data is submitted successfully, but not deleted.
I made a SQL trace to check the queries that the application sends to the database, and I found the below two statements:
exec sp_executesql N'DELETE FROM Log_Ongoing WHERE ActivityDate = #StartDate',N'#startDate datetimeoffset(7)',#startDate='2017-02-12 07:00:00 +02:00'
exec sp_executesql N'INSERT INTO Log_Ongoing (LogType, ActivityDate, ActivityDescription, Train ) VALUES (1,#StartDate, #Activity, #Train)',N'#Train int,#Activity nvarchar(2),#startDate datetimeoffset(7)',#Train=1,#Activity=N'11',#startDate='2017-02-12 07:00:00 +02:00'
When I tested the INSERT staement in the SSMS, it worked fine, but then when I tested the DELETE statement, it didn't work. What is wrong with this query?
Related
Using version:
Microsoft SQL Server 2008 R2 (SP3-OD) (KB3144114) - 10.50.6542.0 (Intel X86)
Feb 22 2016 18:12:09
Copyright (c) Microsoft Corporation
Standard Edition on Windows NT 5.2 <X86> (Build : )
I have a heavy table (135K rows), that I moved from another DB.
It transferred with the [id] column being a standard int column instead of it being the key & seed column.
When trying to edit that field to become an identity specification, with a seed value, its errors out and gives me this error:
Execution Timeout Expired.
The timeout period elapsed prior to completion of the operation...
I even tried deleting that column, to try recreate it later, but i get the same issue.
Thanks
UPDATE:
Table structure:
CREATE TABLE [dbo].[tblEmailsSent](
[id] [int] IDENTITY(1,1) NOT NULL, -- this is what it should be. currently its just an `[int] NOT NULL`
[Sent] [datetime] NULL,
[SentByUser] [nvarchar](50) NULL,
[ToEmail] [nvarchar](150) NULL,
[StudentID] [int] NULL,
[SubjectLine] [nvarchar](200) NULL,
[MessageContent] [nvarchar](max) NULL,
[ReadStatus] [bit] NULL,
[Folder] [nvarchar](50) NULL,
CONSTRAINT [PK_tblMessages] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
I think that your question is a duplicate of Adding an identity to an existing column. That question above has an answer that should be perfect for your situation. I'll reproduce its essential part here below.
But before that, let's clarify why you see the timeout error.
You are trying to add the IDENTITY property to existing column. And you are using SSMS GUI for it. A simple ALTER COLUMN statement can't do it and even if it could, SSMS generates a script that creates a new table, copies over the data into the new table, drops the old table and renames the new table to the old name. When you do this operation via SSMS GUI it runs its scripts with a predefined timeout of 30 seconds.
Of course, you can change this setting in SSMS and increase the timeout, but there is a much better way.
Simple/lazy way
Use SSMS GUI to change the column definition, but then instead of clicking "Save", click "Generate Change Script" in the table designer.
Then save this script to a file and review the generated T-SQL code that GUI runs behind the scene.
You'll see that it creates a temp table with the required schema, copies data over, re-creates foreign keys and indexes, drops the old table and renames the new table.
The script itself is usually correct, but pay close attention to transactions in it. For some reason SSMS often doesn't use a single transaction for the whole operation, but several transactions. I'd recommend to manually review the script and make sure that there is only one BEGIN TRANSACTION at the top and one COMMIT in the end. You don't want to end up with a half-done operation with, say, a table where all indexes and foreign keys were dropped.
If it is a one-off operation, it could be enough for you. Your table is only 2.4GB, so it may take few minutes, but it should not be hours.
If you run the T-SQL script yourself in SSMS, then by default there is no timeout. You can stop it yourself if it takes too long.
Smart and fast way to do it is described in details in this answer by Justin Grant.
The main idea is to use the ALTER TABLE...SWITCH statement to make the change only touching the metadata without touching each page of the table.
BEGIN TRANSACTION;
-- create a new table with required schema
CREATE TABLE [dbo].[NEW_tblEmailsSent](
[id] [int] IDENTITY(1,1) NOT NULL,
[Sent] [datetime] NULL,
[SentByUser] [nvarchar](50) NULL,
[ToEmail] [nvarchar](150) NULL,
[StudentID] [int] NULL,
[SubjectLine] [nvarchar](200) NULL,
[MessageContent] [nvarchar](max) NULL,
[ReadStatus] [bit] NULL,
[Folder] [nvarchar](50) NULL,
CONSTRAINT [PK_tblEmailsSent] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
-- switch the tables
ALTER TABLE [dbo].[tblEmailsSent] SWITCH TO [dbo].[NEW_tblEmailsSent];
-- drop the original (now empty) table
DROP TABLE [dbo].[tblEmailsSent];
-- rename new table to old table's name
EXEC sp_rename 'NEW_tblEmailsSent','tblEmailsSent';
COMMIT;
After the new table has IDENTITY property you normally should set the current identity value to the maximum of the actual values in your table. If you don't do it, new rows inserted into the table would start from 1.
One way to do it is to run DBCC CHECKIDENT after you switched the tables:
DBCC CHECKIDENT('dbo.tblEmailsSent')
Alternatively, you can specify the new seed in the table definition:
CREATE TABLE [dbo].[NEW_tblEmailsSent](
[id] [int] IDENTITY(<max value of id + 1>, 1) NOT NULL,
Im having a bit of a design issue here. Im kind of a novice in this, so I need some help.
Due to a company merge, where everything must go in one of the systems; Im supposed to map our customers with a new customerid in the other company.
When I get the new customerID's Im supposed to ensure that it is unique and the same goes for our existing customerID.
Current customerID: CurCustID
New customer ID: NewCustID
First, I would like the database to make sure that every CurCustID in column CurCustID is unique - only with one record, secondly I would like the column NewCustID to be unique - only with one record.
Third I would like that the row combination of CurCustID and NewCustID only accepts unique data.
If you can help me I would be very thankful, on the otherhand if my approach is bad practice and there is a best practice way of doing this, then please let me know.
USE [Database]
GO
/****** Object: Table [dbo].[TblMapning] Script Date: 05/30/2016 14:30:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[TblMapning](
[CurCustID] [varchar](255) NOT NULL,
[NewCustID] [varchar](255) NOT NULL,
PRIMARY KEY CLUSTERED
(
[CurCustID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
Seems like you'd have to create 3 separate tables to enforce all those things. How new customer ids are generated in the new and mapping tables could be automated depending on your house rules for how new ones are assigned. You would probably want to create code or SPs to make the process more user-friendly, spit out errors, etc. for duped oldcustids, but at the table level this would be one way to enforce it.
CREATE TABLE [dbo].[Tbloldcustids](
CustID [varchar](255) NOT NULL
PRIMARY KEY (CustID)
)
CREATE TABLE [dbo].[Tblnewcustids](
CustID [varchar](255) NOT NULL
PRIMARY KEY (CustID)
)
CREATE TABLE [dbo].[TblMapping](
[CurCustID] [varchar](255) NOT NULL,
[NewCustID] [varchar](255) NOT NULL
PRIMARY KEY (CurCustID,NewCustID)
)
Every other article I see has something to with JOINS... I'm not even trying to do a join! I'm just trying to run a simple UPDATE based off information in a temporary table. Here's the code...
BEGIN TRAN ArchiveMigration
-- insert into temporary table
CREATE TABLE #tblTemp(
[theID] [int] NOT NULL,
[ScheduleID] [int] NOT NULL,
[OverridingCustomerID] [int] NOT NULL,
[Timestamp] [datetime] NOT NULL,
[DeviceName] [nvarchar](max) NULL,
[DestinationTempCool] [int] NULL,
[DestinationMode] [nvarchar](max) NULL,
[DestinationTempHeat] [int] NULL,
CONSTRAINT [PK_#tblTemp] PRIMARY KEY CLUSTERED
(
[theID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
INSERT INTO #tblTemp ([theID], [ScheduleID], [OverridingCustomerID], Timestamp, DeviceName, DestinationTempCool, DestinationMode, DestinationTempHeat)
SELECT Id, ScheduleId, OverridingCustomerId, Timestamp, DeviceName, DestinationTempCool, DestinationMode, DestinationTempHeat
FROM CustomerScheduleOverride
WHERE Id = 836;
-- modify the extended info table
UPDATE ExtendedOverrideInfo
SET ExtendedOVerrideInfo.OverrideId = Null
WHERE ExtendedOverrideInfo.OverrideId = #tblTemp.[theID];
COMMIT TRAN
All I want to do is nullify the values of ExtendedOverrideInfo.OverrideId if said ID exists in the #tblTemp (statement is towards the bottom of the script). Any idea why I might be getting this message? Thanks in advanced!
Your current UPDATE syntax is incorrect, you will need to use a JOIN on your temporary table. This article from Pinal Dave provides a more detailed explanation.
UPDATE ExtendedOverrideInfo
SET ExtendedOverrideInfo.OverrideId = Null
FROM ExtendedOverrideInfo
INNER JOIN #tblTemp t on t.[theID]=ExtendedOverrideInfo.OverrideId
You update statment is totally wrong,the where clause is not correct,you have multiple choices here to resolve your problem:
make join with tmptable
use Exists key in your where clause
Or simply,if your purpose of creating tmptable is just to nullify,why not using cursor?or change your where statment to search record by id?
I have this reasonably sized stored procedure that accepts 3 collections two UDTT collection and one CSV collection.
I have passed the following values to test stored procedure. However the problems occurred in one small master table called EmpDesignations with 5 columns. There is a loop I used in the store procedure to insert values to EmpDesignations. The loop is required because the values are extracted from the CSV string. As expected it does iterate 2 times with two sets of values. The first iteration the data was inserted successfully but in the second iteration data was not inserted. I have checked weather the data is empty but those variables #tmpEmpID and #tmp contain data. So cannot figure out the problem
The EmpDesignations table definition is
EmpID PK, FK not null
DesigID PK, FK not null
IsValid int not null
UpdtDT datetime not null containts to getDate()
AuthID int not null EmpID
here is the snapshot of the table columns and types
In the first iteration the passing values to the insert statement is shown in the watch window
As you can see, ##rowcount is 1 so worked in the first round!
In the following watch shows the passing values to the insert statement, this is in the second iteration:
But the ##rowcount is not 1 therefore the control rollbacks all insertions
Here is a video link of the debugging of the insert statement
here is the video of THE SECOND INSERT statement debugging
Table definition is correct, the number of values passed matches the number of input columns, and the variables are filled with values in both iterations, so what could be the problem???
here is the script that was generated by SQL server for the table EmpDesignations
USE [SMSV100]
GO
/****** Object: Table [dbo].[EmpDesignations] Script Date: 04/12/2014 08:50:23 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[EmpDesignations](
[EmpID] [int] NOT NULL,
[DesigID] [int] NOT NULL,
[IsValid] [int] NOT NULL,
[UpdtDT] [datetime] NOT NULL,
[AuthID] [int] NOT NULL,
CONSTRAINT [PK_EmpDesignations] PRIMARY KEY CLUSTERED
(
[EmpID] ASC,
[DesigID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[EmpDesignations] WITH CHECK ADD CONSTRAINT [FK_EmpDesignations_Designations] FOREIGN KEY([DesigID])
REFERENCES [dbo].[Designations] ([DesigID])
GO
ALTER TABLE [dbo].[EmpDesignations] CHECK CONSTRAINT [FK_EmpDesignations_Designations]
GO
ALTER TABLE [dbo].[EmpDesignations] WITH CHECK ADD CONSTRAINT [FK_EmpDesignations_Employees] FOREIGN KEY([EmpID])
REFERENCES [dbo].[Employees] ([EmpID])
GO
ALTER TABLE [dbo].[EmpDesignations] CHECK CONSTRAINT [FK_EmpDesignations_Employees]
GO
ALTER TABLE [dbo].[EmpDesignations] ADD CONSTRAINT [DF_EmpDesignations_UpdtDT] DEFAULT (getdate()) FOR [UpdtDT]
GO
thanks
I created a script of my database.
But When I run it, the script does not create the database. It skips the "Create db" statement, and only creates the tables (on the database I have selected at the moment, so not ideal....)
(query executes with no errors by the way.)
Why is this happening? why cant you create a database and edit the content in it in one go?
(I know you can check if the db exist first, but this shouldn't be happening from the start)
--My Script--
CREATE DATABASE [EthicsDB]
USE [EthicsDB]
go
CREATE TABLE [dbo].[TempEmployee](
[PersonnelNumber] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](80) NULL,
[SurName] [varchar](80) NULL,
[ManagerEmail] [varchar](80) NULL,
[ManagerName] [varchar](80) NULL,
CONSTRAINT [PK_TempEmployee] PRIMARY KEY CLUSTERED
(
[PersonnelNumber] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
You must use GO after CREATE DATABASE [EthicsDB].
Try this one -
USE [master]
GO
IF EXISTS (
SELECT 1 FROM sys.databases WHERE name = N'EthicsDB'
)
DROP DATABASE [EthicsDB]
GO
CREATE DATABASE [EthicsDB]
GO --<----
USE [EthicsDB]
GO
CREATE TABLE [dbo].[TempEmployee](
[PersonnelNumber] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](80) NULL,
[SurName] [varchar](80) NULL,
[ManagerEmail] [varchar](80) NULL,
[ManagerName] [varchar](80) NULL,
CONSTRAINT [PK_TempEmployee] PRIMARY KEY CLUSTERED
(
[PersonnelNumber] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
If you run the SQL as provided you get an error message on the line
USE [EthicsDB]
This occurs as when SQL Servers runs SQL commands via SQL CMD it process the SQL in batches.
As you have no GO statement after the Create database statement it maybe that SQL Server does not yet recognise that a new database Ethics has been created and thus when you attempt to use the database via USE [EthicsDB] the statement fails.
As your SQL Statements are not wrapped in a transaction and as you are not checking for errors then if SQL Server encounters an error it will raise the error but also continue to process the rest of the query.
In the query provided this leads to the new tables being created in the current database.
To correct the problem modify your query to
CREATE DATABASE [EthicsDB]
go
USE [EthicsDB]
go
You should probably wrap each action in a transaction block.
Also, when you are creating the table I generally do a check to see if it already exists first.
If you run only the create database, what happens?