There are a couple of things confusing me at this level.
I have a table with around 40 columns out of which atleast 35 are in where clause at different times in single execution of a procedure.
When these 35 columns are passed a value via stored procedure, the stored procedure call their respective inline TVF's which in turn call a common multiline TVF.
I need to know if I shall consider creating indexes for all these 35 columns (Though I have serious doubts if that can help, but please tell me I am wrong if it does. )
I am inserting data into a Temporary table . This insert goes on for number of parameters passed to stored procedure and execution plan shows it takes quite a considerable amount of time. Is there a way I can improve the performance here ?
The insert query looks like this :
INSERT INTo #Temp2
(RowNumber,ValFromUser,ColumnName,ValFromFunc,FuncWeight,percentage)
SELECT RowNumber,#firstname,'firstname',PercentMatch,
#constVal,PercentMatch * #constVal FROM dbo.MatchFirstName(#firstname)
:
Execution plan is attached :
execution plan
Table with large number of columns is as follows :
create table Patients
(
Rowid int identity(1,1),
firstname nvarchar(20) not null,
middlename nvarchar(20),
lastname nvarchar(20)not null,
DOB Date,
SSN nvarchar(30),
ZIP nvarchar(10),
[State] nvarchar(2),
City nvarchar(20),
StreetName nvarchar(20),
StreetType nvarchar(20),
BuildingNumber int,
Aptnumber nvarchar(10),
patientnickname nvarchar(20),
patientsMaidenlastname nvarchar(20),
fathersFirstName nvarchar(20),
fatherslastname nvarchar(20),
mothersfirstname nvarchar(20),
motherslastname nvarchar(20),
mothersMaidenlastname nvarchar(20),
citizenship nvarchar(20),
nationality nvarchar(20),
ethnicity nvarchar(20),
race nvarchar(20),
religion nvarchar(20),
primarylanguage nvarchar(20),
patientmrn nvarchar(30),
hospitalname nvarchar(30),
Medicaidid nvarchar(10),
pcpnpi nvarchar(10),
phonenumber nvarchar(15),
email nvarchar(30),
CreatedAt datetime default getdate(),
ModifiedAt datetime DEFAULT getdate(),
CreatedBy nvarchar(128) default SUSER_NAME(),
ModifiedBy nvarchar(128) default SUSER_NAME()
);
Temporary table looks like this :
create table #Temp2
(
Rownumber int not null,
ValFromUser nvarchar(30),
ColumnName nvarchar(30),
ValFromFunc decimal(18, 4),
FuncWeight decimal(18, 4),
Percentage decimal(18, 4) not null,
);
ResultsStored table :
create table ResultsStored
(
Sno int identity(1,1),
SearchSerial int,
StringSearched varbinary(8000),
RowId int,
PercentMatch decimal(18,4),
CreatedAt datetime default getdate(),
ModifiedAt datetime default getdate(),
CreatedBy nvarchar(128) default SUSER_Name(),
ModifiedBy nvarchar(128) default SUSER_NAME(),
HashedKey binary(16)
);
Indexes speed up (sometimes) SELECTs. But indexes slow down INSERTs (and also DELETEs, UPDATEs etc.). So it's a bad idea to have too many indexes.
Quite often SELECT is able to use only one index (or even zero). So all other 34 indexes are nothing of help. Keep only those ones your SELECTs really use.
As you say, you have about 40 columns in a table with at least 35 columns are being mentioned in distinct 'WHERE'-clauses. That is your table not just big, but, which is far worse, it has too many potential keys. It's a very bad design. You need to split it to several tables. Read about normalization.
Related
is is possible to do
DECLARE #guid uniqueidentifier = NEWID();
select #guid
CREATE TABLE #guid
(
[UserId] uniqueidentifier NOT NULL DEFAULT NewID(),
[FirstName] nvarchar(30),
[LastName] nvarchar(30),
[Email] nvarchar(50)
)
I am just trying this concept, if it works in will use it in my web application
the above code does not work
You can't use a dynamic table name directly, but you can first build the SQL in a string variable and execute that; the technique is known dynamic SQL:
DECLARE #guid uniqueidentifier = NEWID();
DECLARE #strSql nvarchar(max)= N'CREATE TABLE ['+cast(#guid as nvarchar(50))+']
(
[UserId] uniqueidentifier NOT NULL DEFAULT NewID(),
[FirstName] nvarchar(30),
[LastName] nvarchar(30),
[Email] nvarchar(50)
)'
select #guid
exec sp_executesql #strSql;
I have added square brackets around the table name because the default representation of a guid has hyphens in it.
If the source of the table name is not a GUID (i.e. it has the potential to contain special characters, user supplied, etc) it is good practice to clean it before using. You can use QUOTENAME() for that purpose:
... + quotename(cast(#guid as nvarchar(50))) + ...
I am able to populate excel sheet's data into a datatable , that table is tempInput (sql fiddle)
Now from that table I want to split data into two tables tbl1,tbl2 (fiddle)
I am facing problem while inserting into tbl2.. let me show you those tables first
create table tempInput
(
question_text nvarchar(100),
description nvarchar(100),
option_1 nvarchar(20),
option_2 nvarchar(20),
option_3 nvarchar(20),
option_4 nvarchar(20),
right_option nvarchar(50)
)
create table tbl1
(
question_id int primary key identity(1,1),
name nvarchar(100),
description nvarchar(100)
)
create table tbl2
(
option_id int IDENTITY(1,1) primary key ,
option_text nvarchar(30),
is_right_option bit,
question_id int
)
lets populate some sample data into tempInput
now I have to split sampleInput's data into two tables as follows..
How can I do that, please find it here
I am getting the Invalid object name 'CUSTOMER_temp'. Error code. I made these two tables and made the temporary table. Also when I put state from inserted. It gives me the error code Invalid column name 'state'. I am not sure if I need this still or if I am able to get rid of it.
The purpose of this trigger is to automatically copy new records to a new table.
DROP TABLE CUSTOMER
CREATE TABLE CUSTOMER
(
CustomerID CHAR(5) PRIMARY KEY, --Make Primary Key
CustLastName VARCHAR(20),
CustFirstName VARCHAR(20),
CustStreet VARCHAR(60),
CustCity VARCHAR(30),
CustState CHAR(2),
CustZip CHAR(5),
CustPhone CHAR(10),
CustEmail CHAR(50),
);
drop table CUSTOMER_temp
CREATE TABLE CUSTOMER_temp -- temporary table
(
CustomerID CHAR(5) PRIMARY KEY,
CustLastName VARCHAR(20),
CustFirstName VARCHAR(20),
CustStreet VARCHAR(60),
CustCity VARCHAR(30),
CustState CHAR(2),
CustZip CHAR(5),
CustPhone CHAR(10),
CustEmail CHAR(50),
);
CREATE TRIGGER dbo.CustCopy
On CUSTOMER
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
insert CUSTOMER_temp (CustomerID, CustLastName, CustPhone, CustState)
Select CustomerID, CustLastName, CustPhone, CustState from inserted
END
Try this... You need INTO after the Insert.
UPDATE removed dbo.
CREATE TRIGGER dbo.CustCopy
On CUSTOMER
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
insert INTO CUSTOMER_temp (CustomerID, CustLastName, CustPhone, CustState)
Select CustomerID, CustLastName, CustPhone, CustState from inserted
END
I have an error when loading a procedure telling me
Cannot insert the value NULL into column 'requestID', table 'MCAST.a01.tbl_enrollmentRequests'; column does not allow nulls. INSERT fails.
Now requestID is a UNIQUEIDENTIFIER type of variable. Is UNIQUEIDENTIFIER an auto generated number or not? Below is a sample of my code where you can see requestID.
CREATE PROCEDURE [a01].[usp_auditAcceptRequest]
(#AccountID UNIQUEIDENTIFIER,
#GroupID UNIQUEIDENTIFIER,
#Reason NVARCHAR(45)
)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [a01].[tbl_enrollmentRequests] (requestDate, groupID, accountID)
VALUES (SYSDATETIMEOFFSET(), #GroupID, #AccountID)
DECLARE #RequestID UNIQUEIDENTIFIER
SET #RequestID = (SELECT requestID
FROM [a01].tbl_enrollmentRequests
WHERE groupID = #GroupID AND accountID = #AccountID)
INSERT INTO [a01].[tbl_enrollmentAudits] (entryDate, requestID, groupID, accountID, accepted, reason)
VALUES (SYSDATETIMEOFFSET(), #RequestID, #GroupID, #AccountID, 1, #Reason)
DELETE FROM [a01].[tbl_enrollmentRequests]
WHERE requestID = #RequestID
END;
GO
Here is where I am implementing the above procedure
BEGIN
DECLARE #AccountID UNIQUEIDENTIFIER;
DECLARE #GroupID UNIQUEIDENTIFIER;
(SELECT #AccountID = accountID
FROM [a01].[tbl_userAccounts] WHERE accountUsername='saraht');
(SELECT #GroupID = groupID FROM [a01].[tbl_groups] WHERE groupName LIKE '%Foo%');
EXECUTE [a01].[usp_addRequest] #AccountID, #GroupID;
END;
GO
Thanks for your help !!
A uniqueidentifier is a normal column, and if you want to have a automatically assigned value you need to add a default to the column. Typically the functions used for the default are newid() or newsequentialid().
Edit based on the posted table definition; you could use this:
CREATE TABLE [a01].[tbl_enrollmentRequests](
requestID UNIQUEIDENTIFIER PRIMARY KEY DEFAULT (NEWID()),
requestDate DATETIMEOFFSET NOT NULL,
groupID UNIQUEIDENTIFIER REFERENCES [a01].[tbl_groups] (groupID) NOT NULL,
accountID UNIQUEIDENTIFIER REFERENCES [a01].[tbl_userAccounts] (accountID) NOT NULL
);
That being said, you can also pre-generate a uniqueidentifier and assign that to a variable in the stored procedure prior to insertion, since the generated GUID can be assumed not to collide with any existing GUID. The benefit of this is that you know the id of the inserted row even without retrieving it from an OUTPUT clause.
A notice on performance: a significant number of rows with a clustered primary key of random GUIDs (as generated bynewid()) are a performance issue, since the inserts will cause many page splits to occur due to the randomness. The newsequentialid() function pretty much completely resolves the performance problem, but it makes the generated GUIDs guessable, so that this can only be used when "random" IDs are not required.
Is UNIQUEIDENTIFIER an auto generated number or not?
What do you ask us? You have a look at the table definition and see whether a default that sets a new uniqueidentifier is defined or not.
If it is not - then no.
If you try to insert null, then also not (as your insert overrides the default value).
---Edit:
As per the table definition you posted:
requestID UNIQUEIDENTIFIER PRIMARY KEY
no default value defined that sets it. So no.
This is my insert statement that I am currently using. The primary key in this table is IDNumber
ALTER procedure [dbo].[AddCustomer]
#IDNumber nvarchar(20),
#Title nchar(10),
#Name nvarchar(50),
#Surname nvarchar(50),
#CellPhone nchar(10),
#AddressLine1 nvarchar(50),
#Suburb nvarchar(40),
#City nvarchar(30),
#PostalCode nchar(10),
#EmailAddress nvarchar(50),
#Password nvarchar(20)
as
insert into Customer(IDNumber,Title,Name,Surname,CellPhone,AddressLine1,Suburb,City,PostalCode,EmailAddress,[Password])
values (#IDNumber,#Title,#Name,#Surname,#CellPhone,#AddressLine1,#Suburb,#City,#PostalCode,#EmailAddress,#Password)
Now I would like the sql statement that will prevent a duplicate email address from being inserted.
You want to look at unique constraints http://msdn.microsoft.com/en-gb/library/ms190024.aspx
ALTER TABLE Customer
ADD CONSTRAINT UC_email UNIQUE (EmailAddress);
GO
That should actually be a constraint on the table column.
ALTER TABLE Customer
ADD CONSTRAINT EmailAddress_Uniqueness_Constraint UNIQUE (EmailAddress)
You can create unique index/key on Email column.
CREATE UNIQUE INDEX IX_Email ON TABLE(EMAIL);