I'm trying to aggregate the result of my query based on the names of members in one dimension. The following will return an error but this is as close as it gets to what I think:
with member [Staff].[Staff Hierarchy].x as
aggregate ([Staff].[Staff Hierarchy].currentmember.name)
select [Measures].[a measure] on 0,
[Staff].[Staff Hierarchy].x on 1
from
(
select [Staff].[Staff Hierarchy].allmembers on 0
from [the cube]
)
Note: I'm basically trying to group by the names as we have multiple records in fact table for one person. Since we are using parent-child hierarchy, I cannot use the name of the staff as an attribute of my dimension.
More details:
I'd like to do something similar to this but instead of "cases" I need the employee names. This would be very similar to group by.
The OPENQUERY must be the last resort as it has serious performance issues. The alternative We've found is as follows:
MEMBER [Staff].[Staff Hierarchy].[Employee number 1] AS
Aggregate ( [Staff].[Staff Hierarchy].&[101], [Staff].[Staff Hierarchy].&[102] )
to automate creating members for all employees, We wrote a query like this:
Declare #mdx varchar(max)
Declare #thisStaffName varchar(500)
declare #thisStaffMember varchar(500)
declare #ThisStaffBusinessKey int
Declare #ThisStaffSurrogateKey int
Declare #TheSet varchar(max)='set CustomEmployeeSet as {[Staff].[Staff Hierarchy].['
set #mdx = 'with member [Staff].[Staff Hierarchy].['
Declare staff_Cursor Cursor for
select distinct top 10 BusinessKey from DIM_Staff order by BusinessKey
open staff_cursor
Fetch Next from staff_Cursor into #ThisStaffBusinessKey
while ##FETCH_STATUS = 0
BEGIN
print 'APN: ' + cast(#ThisStaffBusinessKey as varchar(200))
select #thisStaffName = STAFF_HIER_LEVEL_CD + '-' + FIRST_NM + ' ' +LAST_NM + '-' + CAST(BusinessKey AS VARCHAR(200))
from DIM_Staff
where BusinessKey=#ThisStaffBusinessKey
set #TheSet =#TheSet + #thisStaffName + '],[Staff].[Staff Hierarchy].['
set #mdx = #mdx + #thisStaffName + '] as aggregate('
declare This_Staff_Cursor Cursor for
select STAFF_HIST_ROW_ID from DIM_Staff
where BusinessKey=#ThisStaffBusinessKey
open This_Staff_Cursor
Fetch Next from This_Staff_Cursor into #ThisStaffSurrogateKey
while ##fetch_status =0
begin
print 'SHRI: ' + CAST(#ThisStaffSurrogateKey AS VARCHAR(200))
set #mdx = #mdx + '[Staff].[Staff Hierarchy].&[' + CAST(#ThisStaffSurrogateKey AS VARCHAR(200))
Fetch Next from This_Staff_Cursor into #ThisStaffSurrogateKey
SET #mdx = #mdx + '],'
END
set #mdx = left(#mdx, len(#mdx)-1)
set #mdx = #mdx + ') member [Staff].[Staff Hierarchy].['
close This_Staff_Cursor
DEALLOCATE This_Staff_Cursor
Fetch Next from staff_Cursor into #ThisStaffBusinessKey
END
set #mdx = left(#mdx, len(#mdx)-34)
set #TheSet = left(#TheSet, len(#TheSet)-28)
set #TheSet = #TheSet + '}'
set #mdx = #mdx + ' '+#TheSet
close staff_cursor
deallocate staff_cursor
SELECT #mdx + 'select [the measure] on 0, CustomEmployeeSet on 1 from [the cube] '
A measure should be aggregated already in the cube. In our cubes a script like the following would create "grouped" results per staff member
WITH MEMBER [Measures].[memberName] AS
'[Staff].[Staff Hierarchy].CurrentMember.name'
SELECT
{[Measures].[a measure], [Measures].[memberName]} ON COLUMNS,
[Staff].[Staff Hierarchy].members ON ROWS //<< is there not a level? [Staff].[Staff Hierarchy].[a Level].members ON ROWS
FROM [the cube]
Related
I have below code:
declare #prefix varchar(50)
set #prefix = 'schema1'
declare #TablesAndIdentifiers table (TableT0 varchar(50), TableX0 varchar(50), IdentifierT0 varchar(50), IdentifierX0 varchar(50))
insert into #TablesAndIdentifiers(TableT0, TableX0, IdentifierT0, IdentifierX0)
values
('table1', 'table2', 'external_Id', 'Key Details | External Id')
declare #TableT varchar(50)
declare #TableX varchar(50)
declare #IdentifierT varchar(50)
declare #IdentifierX varchar(50)
------------------------------------------OUTER LOOP------------------------------------------
declare #OuterCursor cursor
set #OuterCursor = cursor for select * from #TablesAndIdentifiers
open #OuterCursor
fetch next from #OuterCursor into #TableT, #TableX, #IdentifierT, #IdentifierX
while(##FETCH_STATUS = 0)
begin
declare #ColList2 table (ColListT varchar(50), ColListX varchar(50))
insert into #ColList2(ColListT,ColListX)
select ColListT, ColListX
from (
select COLUMN_NAME as ColListT, row_number() over (order by table_name) as r from INFORMATION_SCHEMA.Columns
where table_name = #TableT and COLUMN_NAME!=#IdentifierT) a
full outer join
(select COLUMN_NAME as ColListX, row_number() over (order by table_name) as r from INFORMATION_SCHEMA.Columns
where table_name = #TableX and COLUMN_NAME!=#IdentifierX) b
on a.r = b.r
--Declare and set variables containing the query which will insert the mismatch columns into a new table
--#sqlfull is a concatenation of #sqlpre, #sql, #sqlpost, #sqlwhere, #sqlpregroup, #sqlgroupstatement, #sqlpostgroup
--The reason for this is that #sql is the only part of the query we want to be contained in the loop - the others should run outside of the loop
declare #sqlpre varchar(max)
declare #sql varchar(max)
declare #sqlpost varchar(max)
declare #sqlgroupstatement varchar(max)
declare #sqlpostgroup varchar(max)
declare #sqlfull varchar(max)
set #sqlpre = 'select * from (select '
set #sql = ''
set #sqlpost = #IdentifierT + ' from '+#prefix+'.dbo.' +#TableX +' x inner join '+#prefix+'.dbo.' +#TableT + ' t on t.' +#IdentifierT + ' = x.[' + #IdentifierX +'])dt1 group by '
set #sqlgroupstatement = ''
set #sqlpostgroup = ' ' + #IdentifierT
declare #Cursor cursor, #ColListTvar varchar(100), #ColListXvar varchar(100)
set #Cursor = cursor for select * from #ColList2
open #Cursor
fetch next from #Cursor into #ColListTvar,#ColListXvar
Print 'Before While => ' + CAST(##FETCH_STATUS AS varchar(32))
while (##FETCH_STATUS = 0)
begin
Print 'Inside while -=> ' + CAST(##FETCH_STATUS AS varchar(32))
set #sql = #sql + 'case when t.' +#ColListTvar + ' != x.[' +#ColListXvar + '] then 1 else null end as ' + #ColListTvar+'_mismatch, '
set #sqlgroupstatement = #sqlgroupstatement + #ColListTvar+'_mismatch, '
fetch next from #Cursor into #ColListTvar,#ColListXvar
end
close #Cursor
Print 'After While => ' + CAST(##FETCH_STATUS AS varchar(32))
set #sqlfull = concat(#sqlpre,#sql,#sqlpost,#sqlgroupstatement,#sqlpostgroup)
print(#sqlfull)
--exec(#sqlfull)
declare #ColListMismatch varchar(max)
select #ColListMismatch = coalesce(#ColListMismatch+'_count,' ,'') + column_name
from INFORMATION_SCHEMA.COLUMNS where table_name = 'mismatches_' + #TableT and COLUMN_NAME!=#IdentifierT
-- The last column in the list won't get a '_count' in its name (but it needs it as the rest of the code assumes this is the naming convention)
-- See below for workaround to get round this
--Create table variable containing the list of mismatch columns (in which we want to count the non-nulls - non-null implies there has been a mismatch)
declare #ColListMismatchTable table (ColListM varchar(50))
insert into #ColListMismatchTable(ColListM)
select ColListM
from (select [COLUMN_NAME] as ColListM from INFORMATION_SCHEMA.Columns
where table_name = 'mismatches_'+#TableT and COLUMN_NAME!=#IdentifierT)dt1
--Declare variables for use in queries
declare #sqlpre2 varchar(max)
declare #sqlloop varchar(max)
declare #sqlpost2 varchar(max)
declare #sqlfull2 varchar(max)
-- Select counts from the transformation layer table and the XPLAN table; also select the count of the table produced as a result of the inner join between the two
-- If the migration has functioned correctly, these three counts should all be the same
set #sqlpre2 = 'select countXPLAN, countTransfLayer, countXPLAN-countTransfLayer as CountDiff, countMatchedIdentifiers, '
-- As mentioned above, the "+ #ColListMismatch + '_count into " part of the below is necessary to append the _count to the last variable
+ #ColListMismatch + '_count into '+#prefix+'.[dbo].report_' + #TableT + ' from '
set #sqlloop = ''
set #sqlpost2 = ' select * from ((select count(*) as countTransfLayer from '+#prefix+'.dbo.'+#TableT+')dt1 cross join (select count(*) as countXPLAN from '+#prefix+'.dbo.['+#TableX+'])dt2 cross join (select count(*) as countMatchedIdentifiers from '+#prefix+'.dbo.mismatches_'+#TableT+')dt4)'
------------------------------------------SECOND INNER LOOP------------------------------------------
--Use Cursor to create loop to produce counts for each column in mismatches_*
declare #Cursor2 cursor, #ColListMismatchvar varchar(50)
set #Cursor2 = cursor for select * from #ColListMismatchTable
open #Cursor2
fetch next from #Cursor2 into #ColListMismatchvar
while(##FETCH_STATUS = 0)
begin
-- Select all the counts of non-nulls
set #sqlloop = #sqlloop + '(select count(*) as '+ #ColListMismatchvar + '_count from mismatches_' + #TableT + ' where ' + #ColListMismatchvar + '=1)dt_' + #ColListMismatchvar + ' cross join '
fetch next from #Cursor2 into #ColListMismatchvar
end
-- Remove variables so that they can be reused by the next data entity
delete #ColListMismatchTable
select #ColListMismatch=null
close #Cursor2
print('in loop to execute sqlfull2')
set #sqlfull2 = concat(#sqlpre2,#sqlloop,#sqlpost2)
print(#sqlfull2)
-- exec(#sqlfull2)
print('executed sqlfull2')
fetch next from #OuterCursor into #TableT, #TableX, #IdentifierT, #IdentifierX
end
close #OuterCursor
out put of is:
(1 row(s) affected)
(0 row(s) affected)
Before While => -1
After While => -1
select * from (select external_Id from schema1.dbo.table22 x inner join schama1.dbo.table1 t on t.external_Id = x.[Key Details | External Id])dt1 group by external_Id
(0 row(s) affected)
(0 row(s) affected)
in loop to execute sqlfull2..
The problem i am facing code is not going into while loop of below code
declare #Cursor cursor, #ColListTvar varchar(100), #ColListXvar varchar(100)
set #Cursor = cursor for select * from #ColList2
open #Cursor
fetch next from #Cursor into #ColListTvar,#ColListXvar
Print 'Before While => ' + CAST(##FETCH_STATUS AS varchar(32))
while (##FETCH_STATUS = 0)
begin
Print 'Inside while -=> ' + CAST(##FETCH_STATUS AS varchar(32))
set #sql = #sql + 'case when t.' +#ColListTvar + ' != x.[' +#ColListXvar + '] then 1 else null end as ' + #ColListTvar+'_mismatch, '
set #sqlgroupstatement = #sqlgroupstatement + #ColListTvar+'_mismatch, '
fetch next from #Cursor into #ColListTvar,#ColListXvar
end
close #Cursor
Print 'After While => ' + CAST(##FETCH_STATUS AS varchar(32))
set #sqlfull = concat(#sqlpre,#sql,#sqlpost,#sqlgroupstatement,#sqlpostgroup)
print(#sqlfull)
--exec(#sqlfull)
any suggestions will be much appreciated.
Thanks in advance.
After lot of analysis i found that issue with
select ColListT, ColListX
from (
select COLUMN_NAME as ColListT, row_number() over (order by table_name) as r from INFORMATION_SCHEMA.Columns
where table_name = #TableT and COLUMN_NAME!=#IdentifierT) a
full outer join
(select COLUMN_NAME as ColListX, row_number() over (order by table_name) as r from INFORMATION_SCHEMA.Columns
where table_name = #TableX and COLUMN_NAME!=#IdentifierX) b
on a.r = b.r
Instead of Full outer join if i use inner join it worked.
There was issue with number of columns in 2 tables, one of table has less column than other, that's the reason it wasn't working properly.
I need some assistance with my tsql , I have knowledge of sql but mainly just querying tables and im finding tsql and loops quite difficult to finish off.
I have hit a sticking point with my IF STATEMENT.
As you can see I have wrote the loop and attempted some debugging and the code is correct so far.
In the Else section
I need to check if it’s the first time through the loop using #firstloop and then copy all data , its mainly the loop that I’m having problems with and could do with help on getting a starting point.
I am using cursors but have been told it won’t affect performance because it’s not doing too much work and I would appreciate any help with the problem.I have also been told that some sections are Hard coded such as Production2 which should be #Source_Database_Name.
declare #Source_Database_Name varchar(255) = 'Production2';
declare #Destination_Database_Name varchar(255) = 'c365online_script1';
declare #Company_Id int = 1 --declare a companyid
CREATE TABLE #CompanyID (ID bigint)
INSERT INTO #CompanyID(ID)
VALUES('15')
--FIRST CURSOR LOOP THROUGH THIS TABLE
CREATE TABLE #TableList (
processorder int,
tablename NVARCHAR(100)
)
INSERT INTO #TableList (processorder, tablename )
VALUES
(1, 'tProperty');
DECLARE #firstLoop BIT
--SET #firstLoop = true
DECLARE #Counter INT -- counting variable
----------- Cursor specific code starts here ------------
-- company cursor
declare copyCompanyDataCursor CURSOR fast_forward FOR
SELECT ID from #CompanyID;
open copyCompanyDataCursor
fetch next from copyCompanyDataCursor into #Company_Id;
WHILE ##FETCH_STATUS = 0
BEGIN
declare #processorder int;
declare #tablename varchar(500);
-- table cursor
declare copyTableDataCursor CURSOR fast_forward FOR
SELECT processorder,tablename from #TableList order by processorder;
open copyTableDataCursor
fetch next from copyTableDataCursor into #processorder, #tablename;
while ##FETCH_STATUS = 0
BEGIN
SET IDENTITY_INSERT [c365online_script1].[dbo].[tCompany] ON
-- Does the table have a companyID column? if statement checking for company id
IF EXISTS(SELECT * FROM Production2.INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME='CompanyID' and TABLE_NAME=#tablename)
BEGIN
declare #debug varchar(max)
SET #debug = 'INSERT INTO ' + #Destination_Database_Name + '.dbo.' + #tablename + ' SELECT * FROM ' + #Source_Database_Name + '.dbo.' + #tablename + ' WHERE ' + #Source_Database_Name + '.dbo.' + #tablename + '.CompanyID = ' + CAST(#Company_Id as varchar(10))
print #debug
--EXEC(#debug)
--EXEC('INSERT INTO ' + #Destination_Database_Name + '.dbo.' + #tablename + ' SELECT * FROM ' + #Source_Database_Name + '.dbo.' + #tablename + ' WHERE ' + #Source_Database_Name + '.dbo.' + #tablename + '.CompanyID = ' + #Company_Id )
END
ELSE
-- if no check if this is the first time through company loop and copy all data- if #firstloop company exists look at information schema
BEGIN
Print 'No'
END
-- if yes then copy data based on companyID in cursor
--EXEC('INSERT INTO ' + #Destination_Database_Name + '.dbo.' + #tablename + ' SELECT * FROM ' + #Source_Database_Name + '.dbo.' + #tablename )
-- company logic
SET IDENTITY_INSERT [c365online_script1].[dbo].[tCompany] OFF
FETCH NEXT FROM copyTableDataCursor into #processorder,#tablename;
END
close copyTableDataCursor;
Deallocate copyTableDataCursor;
Not sure why you are using the cursor. To answer your question of "checking if its the first time gone through loop" then below is the soullution for this.
Declare a variable above "while ##FETCH_STATUS = 0" Line.
somethign like "Firsttime = 0 "
Under IF , "Firsttime = 1 " Which means this is not first time.
In ELSE , check
---> if "Firsttime = 0 " Then it mean first time
---> if "Firsttime = 1 " Then it mean its not first time
I am using the cursor in my stored procedure; I am hoping to remove the cursor from my SP. Please help me come up with a solution for how to avoid the cursor statement to normal update statement with dynamic.
Example Below:
Update Tablename set columnname(variable) = value from table A join Table B on A.condition = B.Condition where name = 'Test'(variable) and age = 18(variable)
Update Tablename set columnname(variable) = value from table A join Table B on A.condition = B.Condition where name = 'kumar'(variable) and age = 19(variable)
Update Tablename set columnname(variable) = value from table A join Table B on A.condition = B.Condition where name = 'babu'(variable) and age = 30(variable)
This is how my cursor will work. 300 Combination dynamically pick the data from table and update into the main table
I am trying to take out the cursor, and update statement should work similar to this, instead of writing 300 update statements, I want to write one update where all the 300 combinations should execute.
Below is my code which needs this solution:
BEGIN
DECLARE #Type VARCHAR(100)
DECLARE #TargetColumn VARCHAR(100)
DECLARE #SourceColumn VARCHAR(100)
DECLARE #SQL varchar(max)
DECLARE a_cursor CURSOR STATIC
FOR
SELECT [Type],[SourceColumn],[TargetColumn] FROM ref.tblEdsMap
GROUP BY [Type],[SourceColumn],[TargetColumn]
OPEN a_cursor
FETCH NEXT FROM a_cursor INTO #Type,#SourceColumn,#TargetColumn
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = 'UPDATE GCT SET GCT.' + #TargetColumn + ' = map.[TargetValue]
from EdsMap map
JOIN Table GCT
ON GCT.' + #SourceColumn + ' = map.[SourceValue]
where map.[Type]=''' + #Type + ''' and map.SourceColumn=''' + #SourceColumn+ ''''
Exec (#SQL)
PRINT #SQL
FETCH NEXT FROM a_cursor INTO #Type,#SourceColumn,#TargetColumn
END
CLOSE a_cursor
DEALLOCATE a_cursor
END
Rather than use an explicit cursor or a cursor cleverly disguised as a while loop, I prefer row concatenation operations for this type of problem.
DECLARE #cmd NVARCHAR(MAX) = N'';
SELECT #cmd += N'
UPDATE GCT
SET GCT.' + QUOTENAME(TargetColumn) + ' = map.TargetValue
FROM dbo.EdsMap AS map
INNER JOIN dbo.Table AS GCT
ON GCT.' + QUOTENAME(SourceColumn) + ' = map.SourceValue
WHERE map.[Type] = ''' + [Type] + '''
AND map.SourceColumn = ''' + [SourceColumn]+ ''';'
FROM ref.tblEdsMap
GROUP BY [Type], SourceColumn, TargetColumn;
EXEC sp_executesql #sql;
When I've done these in the past, I usually make up a transaction to encompass every update that's needed. Something like this:
CREATE TABLE #targets ([Type] VARCHAR(255),[SourceColumn] VARCHAR(255),[TargetColumn] VARCHAR(255));
INSERT INTO #targets
( [Type], [SourceColumn], [TargetColumn] )
SELECT [Type],[SourceColumn],[TargetColumn] FROM ref.tblEdsMap
GROUP BY [Type],[SourceColumn],[TargetColumn];
DECLARE #sql VARCHAR(MAX);
SET #sql = 'BEGIN TRAN' + CHAR(10) + CHAR(13);
SELECT #sql = #sql +
'UPDATE GCT SET GCT.' + [TargetColumn] + ' = map.[TargetValue]
from EdsMap map
JOIN Table GCT
ON GCT.' + [SourceColumn] + ' = map.[SourceValue]
where map.[Type]=''' + [Type] + ''' and map.SourceColumn=''' + [SourceColumn]+ ''';' + CHAR(10) + CHAR(13)
FROM #targets
SELECT #sql = #sql + 'COMMIT TRAN'
PRINT #sql
Exec (#SQL)
The update statements are still the same, i.e., you get one update per combination. But now you're running as one transaction batch. You could potentially be fancier with the dynamic SQL, so that you had just one update statement, but in my experience, it's too easy to get bad updates that way.
Doing it this way may not be any faster than a cursor. You'd have to test to be sure. With the examples where I've used this approach, it has generally been a faster approach.
Try using a table variable along with a WHILE loop instead, like so:
BEGIN
DECLARE #Type VARCHAR(100)
DECLARE #TargetColumn VARCHAR(100)
DECLARE #SourceColumn VARCHAR(100)
DECLARE #SQL varchar(max)
DECLARE #SomeTable TABLE
(
ID int IDENTITY (1, 1) PRIMARY KEY NOT NULL,
Type varchar(100),
SourceColumn varchar(100),
TargetColumn varchar(100)
)
DECLARE #Count int, #Max int
INSERT INTO #SomeTable (Type, SourceColumn, TargetColumn)
SELECT [Type],[SourceColumn],[TargetColumn]
FROM ref.tblEdsMap
GROUP BY [Type],[SourceColumn],[TargetColumn]
SELECT #Count = 1, #Max = COUNT(ID)
FROM #SomeTable
WHILE #Count <= #Max
BEGIN
SELECT
#Type = Type,
#SourceColumn = SourceColumn,
#TargetColumn = TargetColumn
FROM #SomeTable
WHERE ID = #Count
-- Your code
SET #SQL = 'UPDATE GCT SET GCT.' + #TargetColumn + ' = map.[TargetValue]
from EdsMap map
JOIN Table GCT
ON GCT.' + #SourceColumn + ' = map.[SourceValue]
where map.[Type]=''' + #Type + ''' and map.SourceColumn=''' + #SourceColumn+ ''''
Exec (#SQL)
PRINT #SQL
SET #Count = #Count + 1
END -- while
END
I have one outer cursor and one inner cursor also have two tables to work with. Now with the outer cursor i'm making new columns in the table 1 and naming them by the values from the table two, and that works just fine. Problem is with the inner cursor witch i used to insert the values into those new columns from one specific column from another table. This seams not to work, but what confusing me is that i do not get any error messages. Now i hope you understand what i'm trying to do, here is the code so comment for more description about the problem :
DECLARE #rbr_param nvarchar(255)
DECLARE #vrednost nvarchar(255)
DECLARE #cName nvarchar(255)
DECLARE #sql nvarchar (255)
DECLARE curs CURSOR FOR SELECT DISTINCT rbr_param FROM dbo.parametri_pomocna ORDER BY rbr_param
OPEN curs
FETCH NEXT FROM curs
INTO #rbr_param
WHILE ##FETCH_STATUS = 0
BEGIN
SET #cName = 'P_'+#rbr_param+'_P'
EXEC('ALTER TABLE dbo.Parametri ADD ' + #cName + ' nvarchar(255)')
DECLARE vrd CURSOR FOR SELECT DISTINCT vrednost FROM dbo.parametri_pomocna
OPEN vrd
FETCH NEXT FROM vrd
INTO #vrednost
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'INSERT INTO dbo.Parametri'+(#cName)+ ' SELECT vrednost FROM dbo.parametri_pomocna WHERE vrednost = '+#vrednost+ ' AND rbr_param = '+#rbr_param
if exists (select * from INFORMATION_SCHEMA.COLUMNS where table_name = 'dbo.Parametri' and column_name = '#cName')
begin
exec(#sql)
end
FETCH NEXT FROM vrd
INTO #vrednost
END --end vrd
CLOSE vrd
DEALLOCATE vrd
FETCH NEXT FROM curs
INTO #rbr_param
END
CLOSE curs
DEALLOCATE curs
You have two problems here:
if exists ( select * from INFORMATION_SCHEMA.COLUMNS
where table_name = 'dbo.Parametri'
and column_name = '#cName'
)
(1) This view will never have table_name = schema name and table name.
(2) You have enclosed your variable name in single quotes for some reason.
For both of these reasons, your IF condition will never return true.
Try:
IF EXISTS
(
SELECT 1 FROM sys.columns
WHERE [object_id] = OBJECT_ID('dbo.Parametri')
AND name = #cName
)
(And here is why I prefer catalog views over INFORMATION_SCHEMA.)
Also this double-nested cursor thing seems quite inefficient and a lot more code than necessary to achieve what I think you're trying to do. How about something like this instead:
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'ALTER TABLE dbo.Parametri ADD '
+ QUOTENAME('P_' + rbr_param + '_P') + ' NVARCHAR(255);'
FROM dbo.parametri_pomocna GROUP BY rbr_param;
EXEC sp_executesql #sql;
SET #sql = N'';
SELECT #sql = #sql + N'INSERT dbo.Parametri('+QUOTENAME('P_' + rbr_param + '_P')+ ')
SELECT vrednost
FROM dbo.parametri_pomocna WHERE rbr_param = ''' + rbr_param + '''
GROUP BY vrednost;'
FROM dbo.parametri_pomocna
GROUP BY rbr_param;
EXEC sp_executesql #sql;
For an instance I a select statement and it is returning 1000 rows. I need to execute a particular stored procedure for every row the the select statement is returning.
have you got any idea how can I do that?
Construct the EXECUTE statements in your select like this:
SELECT 'EXEC sp_whatever ' + parameter stuff
FROM your_table
Then run the results! Alternatively, paste your results into a spreadsheet package, and use string concatenation to construct the EXEC statements - just create a formula and paste it down the 1,000 rows. I personally prefer the first approach.
To clarify the "parameter stuff", take the example of a stored procedure that takes two int parameters that you want to take from columns you your_table. You'd then have something like this:
SELECT 'EXEC sp_whatever ' + CAST(field1 AS varchar) + ', ' + CAST(field2 AS varchar)
FROM your_table
Not the need to be careful with string fields here - you run the risk of inadvertently exposing yourself to your own SQL injection attack, as with any SQL string concatenation.
I am reading your "for an instance" as "this is a one-off task". If this is a task that needs automating, then one of the other answers may be the right approach.
You can do it like this:
declare #execstatementsbatch nvarchar(max)
select #execstatementsbatch = ''
SELECT #execstatementsbatch = #execstatementsbatch + 'EXEC UpdateQty ' + ItemCode + ', ' + QtyBO + '; '
FROM ITEMSPO
INNER JOIN .....
<some conditions>
exec(#execstatementsbatch)
Disclaimer: I'm not sure if I understand your question correctly.
Assuming you are on SQL Server 2005 upwards, you could create a table-valued user defined function and use the OUTER APPLY operator in your query.
Most RDBMS will let you select rows from stored procedure result sets. Just put your stored procedures in the FROM clause, as you would for common table expressions. For instance:
SELECT sp.ColumnInResultSet, t.BaseTableColumnName
FROM sp_whatever ( Args) sp INNER JOIN BaseTable t ON t.ID = sp.ID;
CREATE PROCEDURE dbo.usp_userwise_columns_value
(
#userid BIGINT
)
AS
BEGIN
DECLARE #maincmd NVARCHAR(max);
DECLARE #columnlist NVARCHAR(max);
DECLARE #columnname VARCHAR(150);
DECLARE #nickname VARCHAR(50);
SET #maincmd = '';
SET #columnname = '';
SET #columnlist = '';
SET #nickname = '';
DECLARE CUR_COLUMNLIST CURSOR FAST_FORWARD
FOR
SELECT columnname , nickname
FROM dbo.v_userwise_columns
WHERE userid = #userid
OPEN CUR_COLUMNLIST
IF ##ERROR <> 0
BEGIN
ROLLBACK
RETURN
END
FETCH NEXT FROM CUR_COLUMNLIST
INTO #columnname, #nickname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #columnlist = #columnlist + #columnname + ','
FETCH NEXT FROM CUR_COLUMNLIST
INTO #columnname, #nickname
END
CLOSE CUR_COLUMNLIST
DEALLOCATE CUR_COLUMNLIST
IF NOT EXISTS (SELECT * FROM sys.views WHERE name = 'v_userwise_columns_value')
BEGIN
SET #maincmd = 'CREATE VIEW dbo.v_userwise_columns_value AS SELECT sjoid, CONVERT(BIGINT, ' + CONVERT(VARCHAR(10), #userid) + ') as userid , '
+ CHAR(39) + #nickname + CHAR(39) + ' as nickname, '
+ #columnlist + ' compcode FROM dbo.SJOTran '
END
ELSE
BEGIN
SET #maincmd = 'ALTER VIEW dbo.v_userwise_columns_value AS SELECT sjoid, CONVERT(BIGINT, ' + CONVERT(VARCHAR(10), #userid) + ') as userid , '
+ CHAR(39) + #nickname + CHAR(39) + ' as nickname, '
+ #columnlist + ' compcode FROM dbo.SJOTran '
END
--PRINT #maincmd
EXECUTE sp_executesql #maincmd
END
-----------------------------------------------
SELECT * FROM dbo.v_userwise_columns_value