I am searching for a loop query over multiple databases and insert result into existing table in one database to collect al data.
There are 28 existing databases at the moment but when i start the query below it says table already exists at the second database.
when this works i want to loop a much larger query then this.
I also tried executing and union all but if a new database is added it must be collected autmatically.
See example i've tried below:
--drop table if exists [hulptabellen].dbo.HIdatabases
declare #dbList table (dbName varchar(128), indx int)
insert into #dbList
select dbName = dbname, row_number() over (order by dbname)
from [hulptabellen].dbo.HIdatabases
--declare variables for use in the while loop
declare #index int = 1
declare #totalDBs int = (select count(*) from #dbList)
declare #currentDB varchar(128)
declare #cmd varchar(300)
--define the command which will be used on each database.
declare #cmdTemplate varchar(300) =
'
use {dbName};
select * insert into [hulptabellen].dbo.cladrloc from {dbname}.dbo.cladrloc
'
--loop through each database and execute the command
while #index <= #totalDBs
begin
set #currentDB = (select dbName from #dbList where indx = #index)
set #cmd = replace(#cmdTemplate, '{dbName}', #currentDB)
execute(#cmd)
set #index += 1
end
Create the table outside your loop and insert into the table this way:
INSERT INTO [hulptabellen].dbo.cladrloc (col1,col2)
SELECT col1,col2
FROM {dbname}.dbo.cladrloc
FYI: When you use the following syntax, a new table is created, so it can be executed only once.
SELECT *
INTO [hulptabellen].dbo.cladrloc
FROM {dbname}.dbo.cladrloc
I want to create a trigger that does not let you insert a registers if a constraint is not satisfied and also showing an error symbol. But when I create trigger sql-server tells me:
You can only specify an explicit value for identity column in table 'table' when a column list is used and IDENTITY_INSERT is ON.
My code:
create trigger tri1
on table
for insert, update
as
begin
declare #code1 int
declare #code2 int
declare #code3 varchar(20)
declare #nif varchar(12)
declare #date datetime
declare #cost float
insert into table values(#code1, #code2, #code3, #nif,#date, #cost)
if (#cost not between 10 and 100)
begin
RAISERROR('Error', 16, 1);
ROLLBACK;
end
end
I'm working on a MSSQL stored procedure.
I receive a table valued parameter (#accountPropsTVP) and a single variable (#accountID) from the C# server.
#accountPropsTVP has 2 columns:
valueTypeID int
value varchar(max)
Note: I'm never sure how many rows will be in this table.
#accountID is an int.
I need to merge everything received into one table, so that it ends up looking like so:
#temporaryTable:
#accountID (always the same for all rows)
valueTypeID
value
Below is what I have tried, but I get an error:
Msg 112, Level 15, State 4, Procedure insertAccountProps, Line 20
Variables are not allowed in the CREATE TABLE statement.
CREATE PROCEDURE insertAccountProps
-- Received parameters
#accountID int,
#accountPropsTVP accountPropsTVP READONLY
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
-- declare new table
DECLARE #accountPropsTemp TABLE
(
accountID int not null DEFAULT (#accountID),
valueTypeID int not null,
value varchar(max) not null
)
-- insert received TVP into new temp table, so that we can manipulate it (tvp's are read only :( )
INSERT INTO #accountPropsTemp
SELECT *
FROM #accountPropsTVP
-- select all from TVP and add it into temp table created above
INSERT INTO dbo.accountsProps
SELECT *
FROM #accountPropsTemp
END
GO
Maybe there's a simpler way of doing this?
Your issue is here:
DECLARE #accountPropsTemp TABLE
(
accountID int not null DEFAULT (#accountID),
valueTypeID int not null,
value varchar(max) not null
)
You're assigning a variable as a default value which as the error message clearly states is not allowed.
The best option for this is to change your syntax to:
DECLARE #accountPropsTemp TABLE
(
accountID int not null,
valueTypeID int not null,
value varchar(max) not null
)
INSERT INTO
#accountPropsTemp
SELECT
#AccountID
,ValueTypeID
,Value
FROM
#accountPropsTVP
I have custom type (Table type) in sql server 2008.
CREATE TYPE RequestingDatesType AS TABLE
(
LeaveDate datetime,
IsHoliday bit
)
I have a store procedure
CREATE PROCEDURE CreateLeaveRequest
#EmployeeId int,
#LeaveTypeId int,
#LeaveDescription varchar(50)
#TableVariable RequestingDatesType READONLY
AS
DECLARE #LeaveId INT
//1st insert command
INSERT INTO tblLeaveMaster(EmployeeId,LeaveTypeId,LeaveDescription)
VALUES(#EmployeeId,#LeaveTypeId,#LeaveDescription)
SET #LeaveId = SCOPE_IDENTITY()
//2nd insert command
INSERT INTO tblLeaveDetails(LeaveId,LeaveDate,IsHoliday)
VALUES(#LeaveId, LeaveDate(*from custom type*), IsHoliday(*from custom type*))
My question is how can i insert values for 2nd insert command
You must use something like this:
//2nd insert command
INSERT INTO tblLeaveDetails(LeaveId,LeaveDate,IsHoliday)
SELECT #LeaveId, LeaveDate, IsHoliday FROM #TableVariable
I'm trying to debug someone else's SQL reports and have placed the underlying reports query into a query windows of SQL 2012.
One of the parameters the report asks for is a list of integers. This is achieved on the report through a multi-select drop down box. The report's underlying query uses this integer list in the where clause e.g.
select *
from TabA
where TabA.ID in (#listOfIDs)
I don't want to modify the query I'm debugging but I can't figure out how to create a variable on the SQL Server that can hold this type of data to test it.
e.g.
declare #listOfIDs int
set listOfIDs = 1,2,3,4
There is no datatype that can hold a list of integers, so how can I run the report query on my SQL Server with the same values as the report?
Table variable
declare #listOfIDs table (id int);
insert #listOfIDs(id) values(1),(2),(3);
select *
from TabA
where TabA.ID in (select id from #listOfIDs)
or
declare #listOfIDs varchar(1000);
SET #listOfIDs = ',1,2,3,'; --in this solution need put coma on begin and end
select *
from TabA
where charindex(',' + CAST(TabA.ID as nvarchar(20)) + ',', #listOfIDs) > 0
Assuming the variable is something akin to:
CREATE TYPE [dbo].[IntList] AS TABLE(
[Value] [int] NOT NULL
)
And the Stored Procedure is using it in this form:
ALTER Procedure [dbo].[GetFooByIds]
#Ids [IntList] ReadOnly
As
You can create the IntList and call the procedure like so:
Declare #IDs IntList;
Insert Into #IDs Select Id From dbo.{TableThatHasIds}
Where Id In (111, 222, 333, 444)
Exec [dbo].[GetFooByIds] #IDs
Or if you are providing the IntList yourself
DECLARE #listOfIDs dbo.IntList
INSERT INTO #listofIDs VALUES (1),(35),(118);
You are right, there is no datatype in SQL-Server which can hold a list of integers. But what you can do is store a list of integers as a string.
DECLARE #listOfIDs varchar(8000);
SET #listOfIDs = '1,2,3,4';
You can then split the string into separate integer values and put them into a table. Your procedure might already do this.
You can also use a dynamic query to achieve the same outcome:
DECLARE #SQL nvarchar(8000);
SET #SQL = 'SELECT * FROM TabA WHERE TabA.ID IN (' + #listOfIDs + ')';
EXECUTE (#SQL);
Note: I haven't done any sanitation on this query, please be aware that it's vulnerable to SQL injection. Clean as required.
For SQL Server 2016+ and Azure SQL Database, the STRING_SPLIT function was added that would be a perfect solution for this problem. Here is the documentation:
https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql
Here is an example:
/*List of ids in a comma delimited string
Note: the ') WAITFOR DELAY ''00:00:02''' is a way to verify that your script
doesn't allow for SQL injection*/
DECLARE #listOfIds VARCHAR(MAX) = '1,3,a,10.1,) WAITFOR DELAY ''00:00:02''';
--Make sure the temp table was dropped before trying to create it
IF OBJECT_ID('tempdb..#MyTable') IS NOT NULL DROP TABLE #MyTable;
--Create example reference table
CREATE TABLE #MyTable
([Id] INT NOT NULL);
--Populate the reference table
DECLARE #i INT = 1;
WHILE(#i <= 10)
BEGIN
INSERT INTO #MyTable
SELECT #i;
SET #i = #i + 1;
END
/*Find all the values
Note: I silently ignore the values that are not integers*/
SELECT t.[Id]
FROM #MyTable as t
INNER JOIN
(SELECT value as [Id]
FROM STRING_SPLIT(#listOfIds, ',')
WHERE ISNUMERIC(value) = 1 /*Make sure it is numeric*/
AND ROUND(value,0) = value /*Make sure it is an integer*/) as ids
ON t.[Id] = ids.[Id];
--Clean-up
DROP TABLE #MyTable;
The result of the query is 1,3
In the end i came to the conclusion that without modifying how the query works i could not store the values in variables. I used SQL profiler to catch the values and then hard coded them into the query to see how it worked. There were 18 of these integer arrays and some had over 30 elements in them.
I think that there is a need for MS/SQL to introduce some aditional datatypes into the language. Arrays are quite common and i don't see why you couldn't use them in a stored proc.
There is a new function in SQL called string_split if you are using list of string.
Ref Link STRING_SPLIT (Transact-SQL)
DECLARE #tags NVARCHAR(400) = 'clothing,road,,touring,bike'
SELECT value
FROM STRING_SPLIT(#tags, ',')
WHERE RTRIM(value) <> '';
you can pass this query with in as follows:
SELECT *
FROM [dbo].[yourTable]
WHERE (strval IN (SELECT value FROM STRING_SPLIT(#tags, ',') WHERE RTRIM(value) <> ''))
I use this :
1-Declare a temp table variable in the script your building:
DECLARE #ShiftPeriodList TABLE(id INT NOT NULL);
2-Allocate to temp table:
IF (SOME CONDITION)
BEGIN
INSERT INTO #ShiftPeriodList SELECT ShiftId FROM [hr].[tbl_WorkShift]
END
IF (SOME CONDITION2)
BEGIN
INSERT INTO #ShiftPeriodList
SELECT ws.ShiftId
FROM [hr].[tbl_WorkShift] ws
WHERE ws.WorkShift = 'Weekend(VSD)' OR ws.WorkShift = 'Weekend(SDL)'
END
3-Reference the table when you need it in a WHERE statement :
INSERT INTO SomeTable WHERE ShiftPeriod IN (SELECT * FROM #ShiftPeriodList)
You can't do it like this, but you can execute the entire query storing it in a variable.
For example:
DECLARE #listOfIDs NVARCHAR(MAX) =
'1,2,3'
DECLARE #query NVARCHAR(MAX) =
'Select *
From TabA
Where TabA.ID in (' + #listOfIDs + ')'
Exec (#query)