I have the below data available in a table
DECLARE #AddressTbl As Table (ID int identity,Address varchar(100))
INSERT INTO #AddressTbl
VALUES ('State:AndhraPradesh,Dist:Prakasam')
Next time when I enter the same value I should be notified that this value exists in the table.
For this I will use an sp with warning message that the data is available. But I want how to implement the logic to compare the data.
Create Procedure usp_InsertAddress
(
#Address varchar(100)
)
AS
DECLARE #ID INT
SELECT #ID=(SELECT ID FROM #AddressTbl WHERE Address = #Address)
IF #ID IS NULL
BEGIN
INSERT INTO #AddressTbl
VALUES ('State:AndhraPradesh,Dist:Prakasam')
END;
I may enter the address like 'Dist:Prakasam,State:AndhraPradesh'
and there may be some blank spaces also. So need to parse the address and check the key and values.
I will use permanent table instead of table variable.
Appreciate your help.
You can use if exists for check. Or you can add unique CONSTRAINT in your table. The UNIQUE constraint ensures that all values in a column are different. This will return error if you are trying to insert duplicate value.
Create Procedure usp_InsertAddress
(
#Address varchar(100)
)
AS
if exists(SELECT ID FROM #AddressTbl WHERE Address = #Address)
begin
select 'Value is Already Exist in Table'---For Warning
end
else
BEGIN
INSERT INTO #AddressTbl
VALUES ('State:AndhraPradesh,Dist:Prakasam')
select 'Value Inserted Sucessful'---For Success
END;
I have a case that I want to do MERGE statement on a table with a primary key not set to identity and I want to increment the primary key column value within the INSERT part of the MERGE statement.
declare int variable to grab the max Id
declare SQL variable to create sequence dynamically to make start with the max Id determined before
now alter your table to make the primary key column has default constraint that get the next value of the created sequence
do you merge statement
clean up the sequence and the default constraint
Code sample:
DECLARE #id INT;
SELECT #id = MAX(Id) + 1
FROM dbo.Table;
DECLARE #sql NVARCHAR(MAX);
IF OBJECT_ID('tempSeqTable') IS NOT NULL
DROP SEQUENCE [dbo].[tempSeqTable];
SET #sql
= N'CREATE SEQUENCE [dbo].[tempSeqTable] AS INT START WITH ' + CAST(#id AS NVARCHAR)
+ N'INCREMENT BY 1';
EXEC sp_executesql #sql;
ALTER TABLE dbo.Table
ADD CONSTRAINT Id_Default DEFAULT NEXT VALUE FOR tempSeqTable FOR Id;
-- do the merge statement.
ALTER TABLE dbo.Tabel DROP CONSTRAINT Id_Default;
DROP SEQUENCE [dbo].[tempSeqTable];
I have a user-defined table type:
CREATE TYPE [dbo].[EntityKeysTable] AS TABLE
(
[EntityKey] [uniqueidentifier] NOT NULL,
PRIMARY KEY CLUSTERED( [EntityKey] ASC) WITH (IGNORE_DUP_KEY = OFF)
)
And a function that uses it... But that function is being used by different processes in our system and I don't want to go in and have to deal with the new parameter everywhere, so I rather just make it optional by having a default value in it...
ALTER FUNCTION [dbo].[fnMyFunctionNameHere]
(#siteId UNIQUEIDENTIFIER,
#entityKeys AS EntityKeysTable READONLY,
#partialDeploy AS BIT = false)
RETURNS TABLE
AS
RETURN (
WITH Overrides AS (
SELECT * ....
I did it for the #partialDeploy but unsure about how to do the same for the #entityKeys.
I am sorry for my prior misleading information.
Table valued functions cannot be null. But you can define them with no records in it. So, you would check for (select count(*) from #entityKeys) = 0 to check if there are entityKeys or not.
if (select count(*) from #entityKeys) = 0
--load #entityKeys as your wish
Some time ago I also searched for the answer to this question, but found nothing. So I did such:
create PROCEDURE dbo.Test
#table dbo.testType readonly
AS
BEGIN
declare #table2 dbo.testType
if(not exists(select * from #table))
.... do something like
insert into #table2(t1,t2) values ....
else
insert into #table2(t1,t2) select t1,t2 from #table
... do main code using #table2
END
User defined table types is optional. So you may not pass it to function.
I was taking some time trying to write a check constraint that is pointed to a function and I found this article about it:
article about check constraints using functions
My question is: Check Constraints are definitively a better option than triggers?
here you have an example:
CREATE TABLE tmgr.MyTable
(
id INT IDENTITY PRIMARY KEY,
NAME NVARCHAR(50),
TypeId int
)
CREATE FUNCTION dbo.fn_CheckConstraintType
(
#Entity nvarchar(128),
#TypeId int
)
RETURNS int
AS
BEGIN
DECLARE #ReturnValue INT = 0
IF EXISTS (SELECT 1
FROM dbo.TypeEntity
WHERE Entityid = ( SELECT Entityid
FROM dbo.Entity
WHERE Name = #Entity
)
AND TypeId = #TypeId)
SET #ReturnValue = 1
RETURN #ReturnValue
END
Here you have the check constraint
ALTER TABLE dbo.MyTable WITH NOCHECK ADD CONSTRAINT CK_MyTable_CheckConstraintType CHECK (dbo.fn_CheckConstraintType('MyTableType', [TypeId])=1)
I want to be sure that this approach is the best option or there is any other option before using triggers. Check Constraints happen before the insert/update statement is this the main different of using triggers? too many question! sorry!
Thanks
What is the best thing to do in the CREATE and UPDATE stored procedures for a table with default constraints?
When I create a new column for a table, I try to set a propper default value (Default constraint).
Example:
CREATE TABLE Orders
(
O_ID INT NOT NULL
,State INT DEFAULT 0 -- 0 => Not Verified, 1 => Verified, 2 => Processing ....
,P_ID INT
,OrderDate DATE DEFAULT GETDATE()
)
What is the best thing to do in the CREATE and UPDATE stored procedures for this table?
Use the same defaults as in the constraint?
CREATE PROCEDURE UpdateOrder
(
#O_ID INT
,#State INT = 0
,#P_ID INT
,#OrderDate DATE
)
AS
UPDATE
Orders
SET
State = #State
,P_ID = #PID
,OrderDate = #OrderDate
WHERE
O_ID = #O_ID
That would be kind of repetitive, as it's already defaulted in the table.
On the other hand, it allows your parameters to be optional. I would say your choices are to default them to the same as the table (as you suggest), or to default them to null and the table will fill in the default values. The second way is less repetitive and error-prone.
If you want OrderDate to be updated during UPDATE, you need to include it in the UPDATE statement and use getdate() in place of #OrderDate
UPDATE
Orders
SET
State = #State ,
P_ID = #PID ,
OrderDate = getdate()
WHERE O_ID = #O_ID
To comply with DRY, one workaround would be to store your defaults in a table maybe:
CREATE TABLE dbo.MyDefaults
(
OrderState INT
);
INSERT dbo.MyDefaults(OrderState) SELECT 0;
You can't really do this with GETDATE(), so let's just leave that as is - not something you're likely to change, anyway. So now we can pull our default value from the table, instead of hard-coding it. Let's create a scalar function, because we can't use a subquery in a default constraint:
CREATE FUNCTION dbo.DefaultOrderState()
RETURNS INT
AS
BEGIN
RETURN (SELECT TOP (1) OrderState FROM dbo.MyDefaults);
END
GO
(If you have a lot of these, you might consider an EAV approach instead of dedicated columns.)
So now we can have our Orders table, and note that the constant "0" is never mentioned:
CREATE TABLE dbo.Orders
(
O_ID INT NOT NULL,
[State] INT NOT NULL DEFAULT (dbo.DefaultOrderState()),
P_ID INT,
OrderDate DATE NOT NULL DEFAULT (SYSDATETIME())
);
GO
And our update procedure can also grab the defaults (except you haven't defined whether you really want to reset the state to 0 if it is not currently 0 and no value is supplied to the procedure). Again the "0" constant is not mentioned.
CREATE PROCEDURE dbo.UpdateOrder
#O_ID INT,
#State INT = NULL,
#P_ID INT,
#OrderDate DATE = NULL
AS
BEGIN
SET NOCOUNT ON;
UPDATE dbo.Orders
SET [State] = COALESCE(#State, dbo.DefaltOrderState()),
P_ID = #P_ID,
OrderDate = COALESCE(#OrderDate, OrderDate, SYSDATETIME())
WHERE
O_ID = #O_ID;
END
GO
For the update, you could send in null for "No Change" (or another sentinel if the column is nullable). A similar approach would work for inserts.
CREATE PROCEDURE UpdateOrder
(
#O_ID INT
,#State INT
,#P_ID INT = -1
,#OrderDate DATE
)
AS
UPDATE
Orders
SET
State = IsNull(#State,State)
,P_ID = case when #P_ID < 0 then P_ID else #P_ID end -- assuming this int is not nullable and something like -1 is the default value
,OrderDate = COALESCE(#OrderDate,OrderDate)
WHERE
O_ID = #O_ID