sql server programming:
I'm trying to build up a table variable based on a loop that goes through several tables in the database and pulls specific records and drops them into the table variable. Here's what I'm doing: DECLARE @TableName nvarchar(50) DECLARE @SQL nvarchar(255) DECLARE cSyncOrder CURSOR READ_ONLY FAST_FORWARD FOR SELECT TableName FROM SyncOrder ORDER BY Rank DESC OPEN cSyncOrder FETCH NEXT FROM cSyncOrder INTO @TableName WHILE @@FETCH_STATUS = 0 BEGIN --Select into the temp table INSERT INTO @ChangedItems (ID, TableName, ModifiedByID, LastCRC, Modified) SELECT ID, @TableName, ModifiedByID, LastCRC, Modified FROM [@TableName] WHERE Modified >= @AsOf FETCH NEXT FROM cSyncOrder INTO @TableName END CLOSE cSyncOrder DEALLOCATE cSyncOrder It's erroring = the [@TableName] after the from. It takes SELECT ID, @TableName just fine, but I can't get it to use the FROM and take the @TableName as the nvarchar type that it is. I tried Dynamic SQL and of course @ChangedItems isn't delcared in the dymamic SQL command. Since there could be multiple versions of this procedure running at any given time I can't use a temporary table, I need to use a declared variable of type Table (I think, unless someone can come up with a better idea) I also tried: set @SQL = 'INSERT INTO @Items (ID, TableName, ModifiedByID, LastCRC, Modified) SELECT ID, @TheTable, ModifiedByID, LastCRC, Modified FROM @TheTable WHERE Modified >= @AsOf' exec sp_executesql @SQL, '@Items TABLE, @TableName nvarchar(255)', @ChangedItems, @TableName But got an error that @ChangedItems must be a scalar value... Anyone have any suggestions on how to do this effeciently? What I would really love is either a non-cursor based approach (which I've read up on and can't find any that are applicable) or the top one and figure out how to pass a variable for the "FROM" of the select... Thanks! James Hancock
You're close, try: set @SQL = 'SELECT ID, ' + @TableName + ', ModifiedByID, LastCRC, Modified FROM ' + [@TableName] + ' WHERE Modified >= ' + @AsOf INSERT INTO @ChangedItems (ID, TableName, ModifiedByID, LastCRC, Modified) EXEC sp_executesql @SQL -- Sylvain Lafontaine, ing. MVP - Technologies Virtual-PC E-mail: http://cerbermail.com/?QugbLEWINF [quoted text, click to view] "James Hancock" <~james@darwinconsulting.com> wrote in message news:uEdILzvoGHA.4996@TK2MSFTNGP05.phx.gbl... > I'm trying to build up a table variable based on a loop that goes through > several tables in the database and pulls specific records and drops them > into the table variable. > > Here's what I'm doing: > > DECLARE @TableName nvarchar(50) > > DECLARE @SQL nvarchar(255) > > DECLARE cSyncOrder CURSOR READ_ONLY FAST_FORWARD FOR SELECT TableName FROM > SyncOrder ORDER BY Rank DESC > > OPEN cSyncOrder > > FETCH NEXT FROM cSyncOrder INTO @TableName > > WHILE @@FETCH_STATUS = 0 > > BEGIN > > --Select into the temp table > > INSERT INTO @ChangedItems (ID, TableName, ModifiedByID, LastCRC, Modified) > SELECT ID, @TableName, ModifiedByID, LastCRC, Modified FROM [@TableName] > WHERE Modified >= @AsOf > > FETCH NEXT FROM cSyncOrder INTO @TableName > > END > > CLOSE cSyncOrder > > DEALLOCATE cSyncOrder > > > It's erroring = the [@TableName] after the from. It takes SELECT ID, > @TableName just fine, but I can't get it to use the FROM and take the > @TableName as the nvarchar type that it is. I tried Dynamic SQL and of > course @ChangedItems isn't delcared in the dymamic SQL command. > > Since there could be multiple versions of this procedure running at any > given time I can't use a temporary table, I need to use a declared > variable of type Table (I think, unless someone can come up with a better > idea) > > I also tried: > set @SQL = 'INSERT INTO @Items (ID, TableName, ModifiedByID, LastCRC, > Modified) SELECT ID, @TheTable, ModifiedByID, LastCRC, Modified FROM > @TheTable WHERE Modified >= @AsOf' > > exec sp_executesql @SQL, '@Items TABLE, @TableName nvarchar(255)', > @ChangedItems, @TableName > > But got an error that @ChangedItems must be a scalar value... > > Anyone have any suggestions on how to do this effeciently? What I would > really love is either a non-cursor based approach (which I've read up on > and can't find any that are applicable) or the top one and figure out how > to pass a variable for the "FROM" of the select... > > Thanks! > > James Hancock > > >
Oups, sorry, my error: I forgot that you cannot insert int a table variable when using an EXEC statement. I'm not sure why you cannot use a temporary table instead of a table variable. -- Sylvain Lafontaine, ing. MVP - Technologies Virtual-PC E-mail: http://cerbermail.com/?QugbLEWINF [quoted text, click to view] "James Hancock" <~james@darwinconsulting.com> wrote in message news:uEdILzvoGHA.4996@TK2MSFTNGP05.phx.gbl... > I'm trying to build up a table variable based on a loop that goes through > several tables in the database and pulls specific records and drops them > into the table variable. > > Here's what I'm doing: > > DECLARE @TableName nvarchar(50) > > DECLARE @SQL nvarchar(255) > > DECLARE cSyncOrder CURSOR READ_ONLY FAST_FORWARD FOR SELECT TableName FROM > SyncOrder ORDER BY Rank DESC > > OPEN cSyncOrder > > FETCH NEXT FROM cSyncOrder INTO @TableName > > WHILE @@FETCH_STATUS = 0 > > BEGIN > > --Select into the temp table > > INSERT INTO @ChangedItems (ID, TableName, ModifiedByID, LastCRC, Modified) > SELECT ID, @TableName, ModifiedByID, LastCRC, Modified FROM [@TableName] > WHERE Modified >= @AsOf > > FETCH NEXT FROM cSyncOrder INTO @TableName > > END > > CLOSE cSyncOrder > > DEALLOCATE cSyncOrder > > > It's erroring = the [@TableName] after the from. It takes SELECT ID, > @TableName just fine, but I can't get it to use the FROM and take the > @TableName as the nvarchar type that it is. I tried Dynamic SQL and of > course @ChangedItems isn't delcared in the dymamic SQL command. > > Since there could be multiple versions of this procedure running at any > given time I can't use a temporary table, I need to use a declared > variable of type Table (I think, unless someone can come up with a better > idea) > > I also tried: > set @SQL = 'INSERT INTO @Items (ID, TableName, ModifiedByID, LastCRC, > Modified) SELECT ID, @TheTable, ModifiedByID, LastCRC, Modified FROM > @TheTable WHERE Modified >= @AsOf' > > exec sp_executesql @SQL, '@Items TABLE, @TableName nvarchar(255)', > @ChangedItems, @TableName > > But got an error that @ChangedItems must be a scalar value... > > Anyone have any suggestions on how to do this effeciently? What I would > really love is either a non-cursor based approach (which I've read up on > and can't find any that are applicable) or the top one and figure out how > to pass a variable for the "FROM" of the select... > > Thanks! > > James Hancock > > >
I don't think you can pass a table to be used in the statement to sp_executesql. And you can't reference a table variable you've declared in your script in what you pass to sp_executesql. But you can reference a temporary table. And you can use a temporary table. Temporary tables named with one # are local to your connection, so if two or more connections create a table named #MyLocalTable, they do not interfere with each other in any way. Temporary tables named with two #'s are global and are shared by all connections, so at any one time, there can be only one table named ##OurGlobalTable. So one solution is to use a temporary table rather than a table variable, and put the table name into your @SQL string and then use sp_executesql, eg, something like: Create Table #ChangedItems... -- Then inside your FETCH NEXT loop Set @SQL = 'INSERT INTO #ChangedItems (ID, TableName, ModifiedByID, LastCRC, Modified) SELECT ID, ''' + @TableName + ''', ModifiedByID, LastCRC, Modified FROM ''' + @TableName + '''] WHERE Modified >= @AsOf' Exec sp_executesql @SQL, N'@AsOf datetime', @AsOf Of course, when you are finished with this temporary table, you want to drop it. If you don't, then while it won't affect other connections, it will still exist for this connection, and if this same connection tried to create the table again without dropping it first, it would get an error. If you don't drop them, temporary tables live until the connection closes or, if the table was created in a stored procedure, they are dropped when you exit the stored procedure. Tom [quoted text, click to view] "James Hancock" <~james@darwinconsulting.com> wrote in message news:uEdILzvoGHA.4996@TK2MSFTNGP05.phx.gbl... > I'm trying to build up a table variable based on a loop that goes through > several tables in the database and pulls specific records and drops them > into the table variable. > > Here's what I'm doing: > > DECLARE @TableName nvarchar(50) > > DECLARE @SQL nvarchar(255) > > DECLARE cSyncOrder CURSOR READ_ONLY FAST_FORWARD FOR SELECT TableName FROM > SyncOrder ORDER BY Rank DESC > > OPEN cSyncOrder > > FETCH NEXT FROM cSyncOrder INTO @TableName > > WHILE @@FETCH_STATUS = 0 > > BEGIN > > --Select into the temp table > > INSERT INTO @ChangedItems (ID, TableName, ModifiedByID, LastCRC, Modified) > SELECT ID, @TableName, ModifiedByID, LastCRC, Modified FROM [@TableName] > WHERE Modified >= @AsOf > > FETCH NEXT FROM cSyncOrder INTO @TableName > > END > > CLOSE cSyncOrder > > DEALLOCATE cSyncOrder > > > It's erroring = the [@TableName] after the from. It takes SELECT ID, > @TableName just fine, but I can't get it to use the FROM and take the > @TableName as the nvarchar type that it is. I tried Dynamic SQL and of > course @ChangedItems isn't delcared in the dymamic SQL command. > > Since there could be multiple versions of this procedure running at any > given time I can't use a temporary table, I need to use a declared > variable of type Table (I think, unless someone can come up with a better > idea) > > I also tried: > set @SQL = 'INSERT INTO @Items (ID, TableName, ModifiedByID, LastCRC, > Modified) SELECT ID, @TheTable, ModifiedByID, LastCRC, Modified FROM > @TheTable WHERE Modified >= @AsOf' > > exec sp_executesql @SQL, '@Items TABLE, @TableName nvarchar(255)', > @ChangedItems, @TableName > > But got an error that @ChangedItems must be a scalar value... > > Anyone have any suggestions on how to do this effeciently? What I would > really love is either a non-cursor based approach (which I've read up on > and can't find any that are applicable) or the top one and figure out how > to pass a variable for the "FROM" of the select... > > Thanks! > > James Hancock > > >
Thanks! That solves that problem! I was worried that it would create the table and another user connected could end up adding to the same temp table.... good to know that it doesn't work that way! [quoted text, click to view] "Tom Cooper" <tom.no.spam.please.cooper@comcast.net> wrote in message news:a-udnbdLn-s86S3ZnZ2dnUVZ_oednZ2d@comcast.com... >I don't think you can pass a table to be used in the statement to >sp_executesql. And you can't reference a table variable you've declared in >your script in what you pass to sp_executesql. But you can reference a >temporary table. And you can use a temporary table. Temporary tables >named with one # are local to your connection, so if two or more >connections create a table named #MyLocalTable, they do not interfere with >each other in any way. Temporary tables named with two #'s are global and >are shared by all connections, so at any one time, there can be only one >table named ##OurGlobalTable. So one solution is to use a temporary table >rather than a table variable, and put the table name into your @SQL string >and then use sp_executesql, eg, something like: > > Create Table #ChangedItems... > > -- Then inside your FETCH NEXT loop > Set @SQL = 'INSERT INTO #ChangedItems (ID, TableName, ModifiedByID, > LastCRC, Modified) > SELECT ID, ''' + @TableName + ''', ModifiedByID, LastCRC, Modified FROM > ''' + @TableName + '''] > WHERE Modified >= @AsOf' > Exec sp_executesql @SQL, N'@AsOf datetime', @AsOf > > Of course, when you are finished with this temporary table, you want to > drop it. If you don't, then while it won't affect other connections, it > will still exist for this connection, and if this same connection tried to > create the table again without dropping it first, it would get an error. > If you don't drop them, temporary tables live until the connection closes > or, if the table was created in a stored procedure, they are dropped when > you exit the stored procedure. > > Tom > > "James Hancock" <~james@darwinconsulting.com> wrote in message > news:uEdILzvoGHA.4996@TK2MSFTNGP05.phx.gbl... >> I'm trying to build up a table variable based on a loop that goes through >> several tables in the database and pulls specific records and drops them >> into the table variable. >> >> Here's what I'm doing: >> >> DECLARE @TableName nvarchar(50) >> >> DECLARE @SQL nvarchar(255) >> >> DECLARE cSyncOrder CURSOR READ_ONLY FAST_FORWARD FOR SELECT TableName >> FROM SyncOrder ORDER BY Rank DESC >> >> OPEN cSyncOrder >> >> FETCH NEXT FROM cSyncOrder INTO @TableName >> >> WHILE @@FETCH_STATUS = 0 >> >> BEGIN >> >> --Select into the temp table >> >> INSERT INTO @ChangedItems (ID, TableName, ModifiedByID, LastCRC, >> Modified) SELECT ID, @TableName, ModifiedByID, LastCRC, Modified FROM >> [@TableName] WHERE Modified >= @AsOf >> >> FETCH NEXT FROM cSyncOrder INTO @TableName >> >> END >> >> CLOSE cSyncOrder >> >> DEALLOCATE cSyncOrder >> >> >> It's erroring = the [@TableName] after the from. It takes SELECT ID, >> @TableName just fine, but I can't get it to use the FROM and take the >> @TableName as the nvarchar type that it is. I tried Dynamic SQL and of >> course @ChangedItems isn't delcared in the dymamic SQL command. >> >> Since there could be multiple versions of this procedure running at any >> given time I can't use a temporary table, I need to use a declared >> variable of type Table (I think, unless someone can come up with a >> better idea) >> >> I also tried: >> set @SQL = 'INSERT INTO @Items (ID, TableName, ModifiedByID, LastCRC, >> Modified) SELECT ID, @TheTable, ModifiedByID, LastCRC, Modified FROM >> @TheTable WHERE Modified >= @AsOf' >> >> exec sp_executesql @SQL, '@Items TABLE, @TableName nvarchar(255)', >> @ChangedItems, @TableName >> >> But got an error that @ChangedItems must be a scalar value... >> >> Anyone have any suggestions on how to do this effeciently? What I would >> really love is either a non-cursor based approach (which I've read up on >> and can't find any that are applicable) or the top one and figure out how >> to pass a variable for the "FROM" of the select... >> >> Thanks! >> >> James Hancock >> >> >> > >
Don't see what you're looking for? Try a search.
|