Can we define a variable of type array in SQL Server?
I have a table and this pk type is datetime.
CREATE TABLE [dbo].[tblTest]
(
[TestDate] [datetime] NOT NULL, -- this column is the primary key
[UserId] [int] NOT NULL,
[RotationType] [int] NOT NULL
)
And I need a query to update userId
UPDATE TABLE dbo.tblTest
SET RotationType = 1
WHERE TestDate IN (#testDates)
How can I declare this #testDates variable?
you can use table variables:
declare #tblvar as table (TestDate datetime)
insert into #tblvar values (('2021-09-01'),...);
UPDATE TABLE dbo.tblTest
SET RotationType = 1
WHERE TestDate IN (select TestDate from #tblvar)
or you can declare it as type so you can pass it to procs:
declaration phase :
create type DateTimeArray as table (TestDate datetime);
CREATE PROCEDURE funcname (#inputDates DateTimeArray)
as
UPDATE TABLE dbo.tblTest
SET RotationType = 1
WHERE TestDate IN (select TestDate from #inputDates)
end
calling:
declare #tblvar as DateTimeArray;
insert into #tblvar values (('2021-09-01'),...);
exec funcname #tblvar
Related
I have temp table each time store 100 values based on a specific condition.
I need Slno as 1,2,3,4 ...100 each time query executes .
If I use below syntax's, the 'Slno' is taking some other numbers
create table #temptable
(Slno INT IDENTITY(1,1) NOT NULL ,
Name varchar(50)
)
create table #temptable
(Slno int IDENTITY(1,1) PRIMARY KEY ,
Name varchar(50)
)
Please help if there is a way out without using Rank()?
You need to create an IDENTITY column as follows:
Syntax:
CREATE TABLE (
ID_column INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
...
);
It should be
Identity(seed,increment)
Here you go:
CREATE TABLE #temptable
(Slno INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
Name varchar(50)
)
Example:
INSERT INTO #temptable (Name) Values ('ABC')
INSERT INTO #temptable (Name) Values ('ABhshC')
INSERT INTO #temptable (Name) Values ('ABQRAC')
INSERT INTO #temptable (Name) Values ('ABhsAERAYRHAERhC')
SELECT * FROM #temptable
Results:
Slno Name
1 ABC
2 ABhshC
3 ABQRAC
4 ABhsAERAYRHAERhC
I have a table that looks like this :
CREATE TABLE [dbo].[akut_prioritering]
(
[behandling_id] [int] NOT NULL,
[akutstatus] [int] NOT NULL,
[nasta_dag] [bit] NOT NULL,
[sort_order] [bigint] NOT NULL,
[rowversion] [timestamp] NOT NULL,
CONSTRAINT [XPKakut_prioritering]
PRIMARY KEY CLUSTERED ([behandling_id] ASC)
) ON [PRIMARY]
And then I have this stored procedure that tries to update rows in this table :
ALTER PROCEDURE [dbo].[akutlistaSave]
#behandlingSortOrder dbo.akutlista_sortorder_tabletype READONLY
AS
BEGIN
SET NOCOUNT ON;
DECLARE #behandlingId INT;
DECLARE #sortOrder BIGINT;
DECLARE #rowversion ROWVERSION;
DECLARE sortOrderCursor CURSOR LOCAL SCROLL STATIC FOR
SELECT behandling_id, sort_order FROM #behandlingSortOrder
OPEN sortOrderCursor
BEGIN TRAN
FETCH NEXT FROM sortOrderCursor INTO #behandlingId, #sortOrder, #rowversion
WHILE ##FETCH_STATUS = 0
BEGIN
IF EXISTS(SELECT *
FROM akut_prioritering ap
WHERE ap.behandling_id = #behandlingId
AND ap.rowversion = #rowversion)
BEGIN
UPDATE akut_prioritering
SET sort_order = #sortOrder
WHERE behandling_id = #behandlingId;
END
ELSE
BEGIN
RAISERROR ('Rowversion not correct.', 16, 1);
END
FETCH NEXT FROM sortOrderCursor INTO #behandlingId, #sortOrder, #rowversion
END
CLOSE sortOrderCursor
SELECT
ap.behandling_id, ap.rowversion
FROM
akut_prioritering ap
INNER JOIN
#behandlingSortOrder bso ON ap.behandling_id = bso.behandling_id;
DEALLOCATE sortOrderCursor
END
The inparameter type looks like this :
CREATE TYPE [dbo].[akutlista_sortorder_tabletype] AS TABLE
(
[behandling_id] [int] NULL,
[sort_order] [bigint] NULL,
[rowversion] [timestamp] NULL
)
When running this I get a SqlException :
Cannot insert an explicit value into a timestamp column. Use INSERT with a column list to exclude the timestamp column, or insert a DEFAULT into the timestamp column.
From what I understand the rowversion column should be updated with a new value automatically, there is no reason in my case to set it manual.
You can't set the rowversion value in dbo.akutlista_sortorder_tabletype because it is not updateable: it is auto generated
However, rowversion (a.k.a deprecated timestamp) is simply a (var)binary(8) with some special rules. You can define and set a (var)binary(8) in dbo.akutlista_sortorder_tabletype and compare on that in the UPDATE
From the first link
A nonnullable rowversion column is semantically equivalent to a binary(8) column. A nullable rowversion column is semantically equivalent to a varbinary(8) column.
It looks like you are trying to insert a timestamp value in a custom table type and then passing that to your stored procedure. As your error suggests, you cannot insert explicit timestamp values into timestamp columns.
You will need to find a different way of passing you table values to this stored procedure to work.
I am trying to insert data into table using BizTalk with below code. But I am facing error as "Procedure or function Emp_Details has too many arguments specified."
Could someone help me out to solve the same?
ALTER PROCEDURE [dbo].[Emp_Details]
(#InsertDetails InsertDetailsType readonly)
AS
Begin
Truncate table [dbo].[Emp_Details]
INSERT INTO [dbo].[Emp_Details]
(
[NAME],
[DESCRIPTION],
[EMPID]
)
select
[NAME],
[DESCRIPTION],
[EMPID]
from #InsertDetails;
Begin
if exists(select 1 from [dbo].[Emp_Details]where NAME='Raul')
Delete from [Emp_Details]where NAME='Raul'
End
end
Reposting the same sample code used previously for reference.
USE <Database>
GO
/* This is a template table */
CREATE TYPE Emp_Details AS TABLE
( [Name] VARCHAR(100)
, [Description] VARCHAR(100)
, [Address] VARCHAR(100));
GO
/* The following is your Table Emp_Details which you must be having already*/
CREATE TABLE Emp_Details
( [Name] VARCHAR(100)
, [Description] VARCHAR(100)
, [Address] VARCHAR(100));
GO
/* Consider this as your Input Data i.e CSV file or Excel (Note: I have created a table for sample)*/
CREATE TABLE Emp_Details1
( [Name] VARCHAR(100)
, [Description] VARCHAR(100)
, [Address] VARCHAR(100));
GO
INSERT INTO Emp_Details1 VALUES ('John','Test','123')
INSERT INTO Emp_Details1 VALUES ('John1','Test1','1234')
INSERT INTO Emp_Details1 VALUES ('John2','Test2','1235')
GO
SELECT * FROM Emp_Details
/* Declare a variable that references the type. So when you reference a `TYPE` it takes the table template which we created previously*/
DECLARE #Emp AS Emp_Details;
/* Add data to the table variable. In your case push the data that you get into the #Emp */
INSERT INTO #Emp ([Name], [Description], [Address])
SELECT [Name], [Description], [Address]
FROM Emp_Details1;
/* Pass the table variable data to a stored procedure. */
EXEC [dbo].[Insert_Deatils] #Emp;
GO
SELECT * FROM Emp_Details
I have created a scalar function in SQL Server 2008 and the same I am referring in a computed column in few of my tables. Now I want to alter the function without dropping the table. But it throws an error:
Cannot ALTER 'dbo.GetStatus' because it is being referenced by object
'Order'.
Is is possible to alter the function? Or do I drop and create all dependable table first and then alter the function?
Here is my function:
CREATE FUNCTION [dbo].[GetStatus]
(
#FromDate datetime,
#ToDate datetime
)
RETURNS tinyint
AS
BEGIN
declare #ret tinyint;
if(#FromDate<=GETDATE() and (#ToDate>=GETDATE() or #ToDate is null))
set #ret= 1
else
set #ret= 0
return #ret
END
And it is referring in a table:
CREATE TABLE [dbo].[Order](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](200) NOT NULL,
[EffectiveFromDate] [datetime] NOT NULL,
[EffectiveToDate] [datetime] NULL,
[Status] AS ([dbo].[GetStatus]([EffectiveFromDate],[EffectiveToDate]))
)
This is by design. You should first drop all defaults/constraints, then alter your function and the add those constraints back. No need to drop the tables.
But you can work around this by the following trick:
add intermediate function that will call your actual function;
alter computed columns to call intermediate function instead of actual.
Example:
CREATE FUNCTION dbo.fnActual ( #p INT )
RETURNS INT
AS
BEGIN
RETURN #p + 1
END
GO
CREATE FUNCTION dbo.fnIntermediate ( #p INT )
RETURNS INT
AS
BEGIN
RETURN dbo.fnActual(#p)
END
GO
CREATE TABLE TestTable(id INT, fn AS dbo.fnIntermediate(id))
GO
Insert some value:
INSERT INTO dbo.TestTable VALUES ( 1 )
SELECT * FROM dbo.TestTable --selects 2
--throws exception
ALTER FUNCTION dbo.fnIntermediate ( #p INT )
RETURNS INT
AS
BEGIN
RETURN dbo.fnActual(#p)
END
GO
--succseeds
ALTER FUNCTION dbo.fnActual ( #p INT )
RETURNS INT
AS
BEGIN
RETURN #p + 2
END
GO
SELECT * FROM dbo.TestTable --selects 3
ALTER TABLE [dbo].[Order]
DROP COLUMN [Status]
GO
ALTER FUNCTION [dbo].[GetStatus] ...
GO
ALTER TABLE [dbo].[Order]
ADD [Status] AS ([dbo].[GetStatus]([EffectiveFromDate],[EffectiveToDate]))
GO
or even
ALTER TABLE [dbo].[Order]
DROP COLUMN [Status]
GO
ALTER TABLE [dbo].[Order]
ADD [Status] AS CAST(CASE WHEN [EffectiveFromDate] <= GETDATE() AND ([EffectiveToDate] >= GETDATE() OR [EffectiveToDate] IS NULL) THEN 1 ELSE 0 END as tinyint)
GO
How to declare one element table so it can be used in future queries?
DECLARE #Emp TABLE
(
ID BIGINT NULL,
CompanyID BIGINT NULL
)
INSERT INTO #EMP
SELECT ID,CompanyID FROM Emp WHERE PIN = 123
SELECT COMPANYID FROM COMPANY WHERE ID = #Emp.CompanyID
You can not. A table per definition contains a (possibly) unlimited number of elements. However, you can always do something like this:
DECLARE #CompanyID BIGINT
SET #CompanyID = (SELECT TOP 1 CompanyID FROM #Emp WHERE ...)
By the way, the following line is not correct, as the WHERE clause is incomplete.
SELECT COMPANYID FROM COMPANY WHERE #Emp.CompanyID
If you intention is to create a table variable that will only store a maximum of one row, you can do it like this:
DECLARE #Emp TABLE
(
ID BIGINT NULL,
CompanyID BIGINT NULL,
Lock char(1) not null default 'X' primary key check(Lock='X')
)
INSERT INTO #EMP (ID,CompanyID)
SELECT ID,CompanyID FROM Emp WHERE PIN = 123
Because the table's primary key is constrained to only one possible value, logically there can't be more than one row.