SQL Insert with a dynamic Column name - loops

I have a temp table that has all the Names of Column for now there are 4 of them and I am looping through the temp table and do a Insert into another table, Now the issue is that the Column name that I want to insert depends on what it gets from the loop:
Here is the code:
Declare #OutputTable table
(
RowID int IDENTITY(1, 1),
ClientID int,
ClientName VarChar(100),
ScoreModule1 VarChar(100),
ScoreModule2 VarChar(100),
ScoreModule3 VarChar(100),
ScoreModule4 VarChar(100)
)
Declare #TempModuleNumber table
(
RowIDNumber int IDENTITY(1, 1),
ModuleNumber varchar (300)
)
INSERT INTO #TempModuleNumber(ModuleNumber)
VALUES ('ScoreModule1'), ('ScoreModule2'),
('ScoreModule3'), ('ScoreModule4')
Declare #ModuleRowCountNumber int
Declare #ModuleCounterNumber int
Declare #ModuleNumber varchar(300)
Select #ModuleRowCount = COUNT(#ModuleNumber)
from #TempModuleNumber
set #ModuleCounterNumber = 1
while #ModuleCounterNumber <= #ModuleRowCount
begin
Select #ModuleNumber = ModuleNumber
from #TempModuleNumber
where RowIDNumber = #ModuleCounterNumber
Insert into #OutputTable (ClientID, ClientName, #ModuleNumber) --This is where the problem is the #ModuleNumber is. I get a "syntax error". Is there another way of doing this to it depends on what it gets from the Loop?
Set #ModuleCounterNumber = #ModuleCounterNumber + 1
END

I only made change to the necessary part:
while #ModuleCounterNumber <= #ModuleRowCount
begin
Select #ModuleNumber = ModuleNumber
from #TempModuleNumber
where RowIDNumber = #ModuleCounterNumber
DECLARE #SQL VARCHAR(MAX)
SET #SQL =
'
Insert into #OutputTable (ClientID, ClientName, ' + #ModuleNumber + ')
SELECT A,B,C //<----------- THIS IS THE MISSING PART I WAS TALKING ABOUT
'
EXEC(#SQL)
Set #ModuleCounterNumber = #ModuleCounterNumber + 1
END

Related

Have this problem with calling stored procedure unknown object type

I am trying to write a query that needs to call a stored procedure. But it always throws an error:
Unknown object type 'TABLEIXICHistoricalData' used in a CREATE, DROP, or ALTER statement.
This is query:
USE ETLCourse
DECLARE #LOOP TABLE
(
ID INT IDENTITY(1,1),
TableName NVARCHAR(100)
)
INSERT INTO #LOOP (TableName)
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE '%_Stocks%'
DECLARE #b INT = 1, #m INT, #t NVARCHAR(100)
SELECT #m = MAX(ID) FROM #LOOP
WHILE #b <= #m
BEGIN
SELECT #t = TableName
FROM #LOOP
WHERE ID = #b
EXECUTE [dbo].[stp_BuildNormalizedTable] #t
SET #b = #b + 1
END
and here is the procedure:
ALTER PROCEDURE [dbo].[stp_BuildNormalizedTable]
#table NVARCHAR(100)
AS
BEGIN
DECLARE #cleanTable NVARCHAR(100),
#s NVARCHAR(MAX)
SET #cleanTable = REPLACE(#table, '_Stocks', 'HistoricalData')
SET #s = 'CREATE TABLE' + #cleanTable + '(ID INT IDENTITY(1,1), Price DECIMAL(13, 4), PriceDate DATE)
INSERT INTO' + #cleanTable + '(Price,PriceDate) SELECT [Adj Close],[Date] FROM'
+ #table + ' ORDER BY Date ASC'
--PRINT #s
EXECUTE sp_executesql #s
END
It should copy two specific column and create a new table by using #Loop table and procedure
You need to add 'space' after 'create table' and 'insert into' and 'from'
declare #s nvarchar(max)
declare #cleantable nvarchar(100)
declare #table nvarchar(100)
set #cleantable = 'aaa'
set #table = 'bbb'
SET #s = 'CREATE TABLE' + #cleanTable + '(ID INT IDENTITY(1,1),Price Decimal(13,4),PriceDate DATE)
Insert into' + #cleanTable
+ '(Price,PriceDate) SELECT [Adj Close],[Date] FROM'
+ #table + ' ORDER BY Date ASC'
print #s
Output:
CREATE TABLEaaa(ID INT IDENTITY(1,1),Price Decimal(13,4),PriceDate DATE)
Insert intoaaa(Price,PriceDate) SELECT [Adj Close],[Date] FROMbbb ORDER BY Date ASC
Use 'print' to check your query.

Add columns dynamically and Later Parse values in the respective columns

I have an SP which accepts the Inputtable as parameter, My Inputtable is as shown in the code
`create table inputTable ( id int,ItemQty varchar(100))
insert into inputTable(id, ItemQty) values(1,'a,b,c')
insert into inputTable(id, ItemQty) values(2,'x,y')
insert into inputTable(id, ItemQty) values(3,'l,m,n,o,p')
insert into inputTable(id, ItemQty) values(4,'a,b')
insert into inputTable(id, ItemQty) values(5,'m')`
and SP i have written is like below
`ALTER PROCEDURE [dbo].[Column_Dynamics] (#tablename varchar(50))
AS
BEGIN
-----
declare #maxcount as int
set #maxcount='select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+#tablename
exec('select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+#tablename)
print #maxcount
exec #maxcount
print #maxcount
declare #var varchar(100)
IF EXISTS(SELECT * FROM sys.columns WHERE object_id = Object_id(#tablename))
set #var='alter table '+ #tablename +' ADD column QTY1'
exec(#var)
select * from #tablename
select max(len(ItemQty))-max(len(replace(ItemQty, ',', ''))-1) from inputtable
END`
My table is :
step 1 ) I want to add the columns dynamically to inputtable like QTY1,QTY2,QTY3,QTY4,QTY5 because maximum count of ItemQty column is 5, by considering comma as delimiter as shown in figure1
**step 2) ** Parse values in the respective columns(by considering the delimiter comma (,).as shown in figure2
Later SP: I got till here, But Not getting the second step, that is update Parse values in the respective columns.
ALTER PROCEDURE dynamic_tbl (#tablename varchar(50))
AS
BEGIN
DECLARE #ColumnCount int
DECLARE #rowcount TABLE (Value int);
INSERT INTO #rowcount
EXEC('select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+#tablename);
SELECT #ColumnCount = Value FROM #rowcount;
Declare #ColumnName nvarchar(10)='qty_'
Declare #count int =0
IF(#ColumnCount>0)
BEGIN
IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'dyn_tbl'))
BEGIN
DROP TABLE dyn_tbl
END
select * into dyn_tbl from inputtable
SET #count=#count +1;
WHile(#ColumnCount>=#count)
BEGIN
SET #ColumnName='qty_'+CONVERT(varchar(2),#count)
EXEC ('ALTER TABLE dyn_tbl ADD ['+#ColumnName +'] varchar(20)')
declare #myvar as varchar(max)
set #myvar='update '+#tablename+' set '+#ColumnName +' =itemQty'
--exec dynamic_tbl 'dyn_tbl'
--select * from dyn_tbl
--CAST('<A>'+REPLACE(ITEMQTY, ',', '</A><A>')+'</A>' AS XML)
print #myvar
exec(#myvar)
SET #count=#count +1;
END
END
----
END
Procedure to alter given table dynamically based on column length as you have asked
Alter PROCEDURE [dbo].[Column_Dynamics] (#tablename varchar(50))
AS
BEGIN
drop table ##temp
declare #query1 varchar(max)
exec ( '
create table ##temp (id int identity,columnsl varchar(100))
declare #maxcount as int
set #maxcount = (select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+#tablename+')
declare #count int = 1
while (#count <= #maxcount)
begin
declare #colvar nvarchar(100)= ''QTY''
set #colvar = concat(#colvar,#count)
set #count = #count + 1
insert into ##temp select #colvar
end
')
declare #tempstart int = 1
declare #templast int = (select count(*) from ##temp)
declare #updatecol varchar(100) = ''
while (#tempstart <= #templast)
Begin
set #updatecol = (select columnsl from ##temp where id = #tempstart)
exec ('alter table '+#tablename+' Add '+#updatecol+' varchar(100) ')
set #tempstart = #tempstart + 1
end
End
output for inputTable:
id ItemQty QTY1 QTY2 QTY3 QTY4 QTY5
1 a,b,c NULL NULL NULL NULL NULL
2 x,y NULL NULL NULL NULL NULL
3 l,m,n,o,p NULL NULL NULL NULL NULL
4 a,b NULL NULL NULL NULL NULL
5 m NULL NULL NULL NULL NULL
may not be the best way but works.
edit
Altered above procedure to perform both actions, Please use below procedure
Alter PROCEDURE [dbo].[Column_Dynamics] (#tablename varchar(50))
AS
BEGIN
-- declare #tablename varchar(100) = 'inputTable'
drop table #temp if object_id('temp..#temp') is not null drop table #temp
declare #query1 varchar(max)
create table #temp (id int identity,columnsl varchar(100))
exec ( '
declare #maxcount as int
set #maxcount = (select MAX(len(ITEMQTY) - len(replace(ITEMQTY, '','', '''')) +1) from '+#tablename+')
declare #count int = 1
while (#count <= #maxcount)
begin
declare #colvar nvarchar(100)= ''QTY''
set #colvar = concat(#colvar,#count)
set #count = #count + 1
insert into #temp
select #colvar
end
')
declare #tempstart int = 1
declare #templast int = (select count(*) from #temp)
declare #updatecol varchar(100) = ''
declare #itemqty varchar(100)
while (#tempstart <= #templast)
Begin
set #updatecol = (select columnsl from #temp where id = #tempstart)
exec ('alter table '+#tablename+' Add '+#updatecol+' varchar(100) ')
set #tempstart = #tempstart + 1
end
declare #sysvar table (id int identity,cols varchar(100))
insert into #sysvar select sys.columns.name AS ColumnName FROM sys.columns JOIN sys.tables ON sys.columns.object_id = sys.tables.object_id WHERE sys.tables.name = 'inputTable'
declare #finvar table (id int identity,cols varchar(100))
insert into #finvar select cols from #sysvar where id not in (1,2)
declare #cat int = 1 declare #dog int = (select max(id) from inputTable)
while (#cat <= #dog)
begin
drop table #tab2
if object_id('temp..#tab2') is not null drop table #tab2
create table #tab2 (id int identity,fnvalues varchar(100))
set #itemqty = (select itemqty from inputTable where id = #cat)
insert into #tab2 select item from [dbo].[fnSplit](#itemQty,',')
declare #cn int = 1
declare #max int = (select max(id) from #tab2)
declare #sql nvarchar (1000);
while (#cn <= #max)
begin
declare #upcol varchar(100) = (select fnvalues from #tab2 where id = #cn)
declare #plscol varchar(100) = (select cols from #finvar where id = #cn)
set #sql = N'update '+#tablename+' set ' + #plscol + '= '''+#upcol+''' where id = '''+cast(#cat as varchar(10))+''' ';
select #sql
exec sp_executesql #sql;
set #cn = #cn + 1
end
set #cat = #cat + 1
End
End
output:
id ItemQty QTY1 QTY2 QTY3 QTY4 QTY5
1 a,b,c a b c NULL NULL
2 x,y x y NULL NULL NULL
3 l,m,n,o,p l m n o p
4 a,b a b NULL NULL NULL
5 m m NULL NULL NULL NULL
did not optimize the query but works fine.
However, if you have maximum Qty's are known which are in comma separated format then you could use xml node method to separate them into columns.QTY1...QTY5
SELECT DISTINCT ID, ITEMQTY,
a.value('/A[1]', 'VARCHAR(MAX)') as QTY1,
a.value('/A[2]', 'VARCHAR(MAX)') as QTY2,
a.value('/A[3]', 'VARCHAR(MAX)') as QTY3,
a.value('/A[4]', 'VARCHAR(MAX)') as QTY4,
a.value('/A[5]', 'VARCHAR(MAX)') as QTY5
FROM
(
SELECT ID, ITEMQTY,
CAST('<A>'+REPLACE(ITEMQTY, ',', '</A><A>')+'</A>' AS XML) AS ITEMQTY1
FROM inputTable
) A
CROSS APPLY ITEMQTY1.nodes('/A') AS split(a);
Result :
ID ITEMQTY QTY1 QTY2 QTY3 QTY4 QTY5
1 a,b,c a b c NULL NULL
2 x,y x y NULL NULL NULL
3 l,m,n,o,p l m n o p
4 a,b a b NULL NULL NULL
5 m m NULL NULL NULL NULL
Later, you could replace null by using coalesce() or isnull() function with ''
Use This
First Create a function
CREATE FUNCTION [dbo].[fn_split](
#str VARCHAR(MAX),
#delimiter CHAR(1)
)
RETURNS #returnTable TABLE (idx INT PRIMARY KEY IDENTITY, item VARCHAR(8000))
AS
BEGIN
DECLARE #pos INT
SELECT #str = #str + #delimiter
WHILE LEN(#str) > 0
BEGIN
SELECT #pos = CHARINDEX(#delimiter,#str)
IF #pos = 1
INSERT #returnTable (item)
VALUES (NULL)
ELSE
INSERT #returnTable (item)
VALUES (SUBSTRING(#str, 1, #pos-1))
SELECT #str = SUBSTRING(#str, #pos+1, LEN(#str)-#pos)
END
RETURN
END
GO
and use function like this
Declare #test TABLE (
ID VARCHAR(200),
Data VARCHAR(200)
)
insert into #test
(ID, Data)
Values
(1,'a,b,c')
insert into #test
(ID, Data )
values(2,'x,y')
insert into #test
(ID, Data )
values(3,'l,m,n,o,p')
insert into #test
(ID, Data )
values(4,'a,b')
insert into #test
(ID, Data )
values(5,'m')
select ID,data AS ItemQty,
ISNULL((select item from fn_split(Data,',') where idx in (1)),'') as QTY1 ,
ISNULL((select item from fn_split(Data,',') where idx in (2)),'') as QTY2,
ISNULL((select item from fn_split(Data,',') where idx in (3)),'') as QTY3,
ISNULL((select item from fn_split(Data,',') where idx in (4)),'') as QTY5 ,
ISNULL((select item from fn_split(Data,',') where idx in (5)),'') as QTY5
from #test
Output Same as your Image
instead of using
insert into #test
(ID, Data)
Values
(1,'a,b,c')
you can also assgin it like this
insert into #test
(ID, Data)
Values
(Select Column1, Column2 From YourTable)

Id auto increment varchar not increments

I am using a VARCHAR column as my primary key. I want to auto increment it (base 62, lower/upper case, numbers), However, the below code fails (for obvious reasons):
CREATE TABLE TESTING
(
ID VARCHAR(10),
NAME VARCHAR(15),
DESCP VARCHAR(50)
);
Creating a procedure for testing insert of a new record with NVARCHAR auto-incremented ID:
CREATE PROCEDURE SP_INSERT
#NAME VARCHAR(MAX), #DESCP VARCHAR(MAX)
AS
BEGIN
/* Logic for getting new ID as per the NAME with PRE FIX */
DECLARE #NEWID VARCHAR(5);
DECLARE #PREFIX VARCHAR(10);
SET #PREFIX = UPPER(SUBSTRING('STR', 1, 3))
SELECT #NEWID = (#PREFIX + replicate('0', 3 - len(CONVERT(VARCHAR, N.OID 1))) + CONVERT(VARCHAR, N.OID + 1))
FROM
(SELECT
CASE
WHEN MAX(T.TID) IS NULL
THEN 0 ELSE MAX(T.TID)
END AS OID
FROM
(SELECT SUBSTRING(ID, 1, 1) AS PRE_FIX,
SUBSTRING(ID, 2, LEN(ID)) AS TID
FROM Testing) AS T
WHERE
T.PRE_FIX = #PREFIX) AS N
/* INSERT QUERY FOR NEW RECORD */
INSERT INTO Testing VALUES (#NEWID, #NAME, #DESCP)
END
I try to insert a values:
SP_INSERT 'svce','YOUR MANAGEMENT DESCRIPTION';
this first time, again try to inset I got same ID is not incremented.
Like:
ID Name
------------
SVC001 SVCE
SVC001 Svce
You could try to use COMPUTED COLUMN something like that:
create table t
(
Id int auto_increment,
ComputedId as 'SVC' + convert(nvarchar(60), lpad(Id,3,'0')),
Data nvarchar(60)
)
I MADE ONE SMALL SCRIPT,
declare #t table (id varchar(10))
insert into #t values ('SVC001'),('SVC20902')
Declare #NEWID int
select #NEWID=isnull(max(replace(id,'SVC',''))+1,1) from #t
select 'SVC'+ replicate('0',CASE WHEN 3-len(#NEWID)<=0
THEN 0 ELSE 3-len(#NEWID) END)+cast(#NEWID as varchar(10))
Finally I got solution for Auto_Increment ID. I done following code for solution. code is:
alter PROCEDURE SP2_INSERT
#NAME VARCHAR(MAX),
#DESCP VARCHAR(MAX)
AS
BEGIN
DECLARE #NEWID VARCHAR(10);
DECLARE #PREFIX VARCHAR(MAX);
SET #PREFIX = UPPER(SUBSTRING(#NAME,1, 3))
SELECT #NEWID = (#PREFIX + replicate('0', 3 - len(CONVERT(VARCHAR,N.OID + 1))) + CONVERT(VARCHAR,N.OID + 1)) FROM (
SELECT CASE WHEN MAX(T.TID) IS null then 0 else MAX(T.TID) end as OID FROM (
SELECT SUBSTRING(EmployeeID, 1, 1) as PRE_FIX,SUBSTRING(EmployeeID, 2, LEN(EmployeeID)) as TID FROM EmployeeMasters
) AS T WHERE T.PRE_FIX = #PREFIX
) AS N
INSERT INTO Testing VALUES (#NEWID,#NAME,#DESCP)
end
Try this,
DECLARE #table TABLE(ID VARCHAR(10),
NAME VARCHAR(15),
DESCP VARCHAR(50))
DECLARE #NEWID VARCHAR(5);
DECLARE #PREFIX VARCHAR(10);
SET #PREFIX = UPPER(SUBSTRING('STR', 1, 3))
SELECT #NEWID=CAST(ISNULL(MAX(CAST(SUBSTRING(ID,4,LEN(ID)) AS INT)),0)+1 AS varchar) FROM #table
INSERT INTO #table(DESCP,ID,NAME)
SELECT 'zzzz',(#PREFIX + replicate('0', 3 - len(CONVERT(VARCHAR,#NEWID))))+#NEWID,'fsf'
SELECT #NEWID=CAST(ISNULL(MAX(CAST(SUBSTRING(ID,4,LEN(ID)) AS INT)),0)+1 AS varchar) FROM #table
INSERT INTO #table(DESCP,ID,NAME)
SELECT 'zzzz',(#PREFIX + replicate('0', 3 - len(CONVERT(VARCHAR,#NEWID))))+#NEWID,'fsf'
SELECT * FROM #table

Get Float value with Comma separtor

Am new to Sql server ce. my table have float value. I want select float with comma separated and decimal position. like this
table name table1
val
1220333
222
36535
I want result like this
val
12,20,333.00
222.00
36,535.00
like indian Rupees
Am using Sql server ce 3.5
DECLARE #Table1 TABLE
(val int)
;
INSERT INTO #Table1
(val)
VALUES
(1220333),
(222),
(36535)
;
select convert(varchar(50), CAST(val as money), -1) amount from #Table1
select FORMAT(CAST(val AS MONEY),'N','en-in') amount from #Table1
OR
Function
create function to_indian_currency(#n decimal(25,5))
returns varchar(100) as
BEGIN
declare #a varchar(100) = cast(#n as varchar(100))
declare #dec_part varchar(100) =
(select substring(#a, charindex('.',#a), len(#a)-charindex('.',#a)+1))
declare #int_part varchar(100) = (select left(#a, charindex('.',#a)-1))
declare #f int = cast(#int_part as bigint)%1000
declare #q int = cast(#int_part as bigint)/1000
declare #final varchar(100) = ''
while #q > 0
begin
set #final = cast(#q%100 as varchar) + ',' + #final
set #q = #q/100
end
RETURN #final + cast(#f as varchar) + #dec_part
END
select dbo.to_indian_currency(val) from #Table1

split string by " " in a sql query

there is a string is "'CNY','THB','USD','VND'" pass from coding.
is there any way that can split it into 'CNY','THB','USD','VND' because I was doing a IN statement. It cannot be done with "'CNY','THB','USD','VND'".
You can use this function, if you are using Microsoft SQL. It will return a table, and in your case you can easily specify if a string in question is in the result set of this table. I am showing you how to use it below
create FUNCTION [dbo].[SPLITSTRING]
(
#CSV varchar(max),
#Delimiter char(1)
)
RETURNS
#Split TABLE (Id int identity(1,1),[OutParam] varchar(max))
AS
BEGIN
Declare #Len as int, #Pos1 int, #Pos2 int
IF LTRIM(RTRIM(#CSV)) = ''
RETURN
SELECT #CSV = #Delimiter + #CSV + #Delimiter
select #Len = len(#csv), #Pos1 = 1
While #Pos1 < #Len
Begin
select #Pos2 = charindex(#Delimiter,#CSV,#Pos1 + 1)
insert #Split select ltrim(rtrim(substring(#csv, #Pos1+1, #Pos2 - #pos1 -1)))
select #Pos1 = #Pos2
End
RETURN
END
Then do
select * from [dbo].[SPLITSTRING]('CNY,THB,USD,VND',',')
What I am doing is creating a table, and splitting out the string between ",", and returning a table.
From above answer , no need of single quote. Pass the string as 'CNY,THB,USD,VND'
in query
Where Varchar_Field IN (select * from [dbo].[SPLITSTRING] ('CNY,THB,USD,VND',','))
Create a Table Vlaued Function
Create FUNCTION [dbo].[Split]
(
#RowData nvarchar(2000),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table
(
Data nvarchar(100)
)
AS
BEGIN
Declare #Cnt int
Set #Cnt = 1
While (Charindex(#SplitOn,#RowData)>0)
Begin
Insert Into #RtnValue (data)
Select
Data = ltrim(rtrim(Substring(#RowData,1,Charindex(#SplitOn,#RowData)-1)))
Set #RowData = Substring(#RowData,Charindex(#SplitOn,#RowData)+1,len(#RowData))
Set #Cnt = #Cnt + 1
End
Insert Into #RtnValue (data)
Select Data = ltrim(rtrim(#RowData))
Return
END
And Create a table where you want to use split string
Declare #SplitString Table
(
SubjectName nvarchar(50)
)
and Call The Function
INSERT INTO #SplitString SELECT * FROM dbo.Split("Your String",'Character from which you want to split')

Resources