|
database
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Unknown Columns!which I am using a stored procedure but while coding, I am not aware of the no. of columns existing in that DB table. Neither am I aware of the column names while coding. Also more columns can get added to the table in the future. What I want to do is retrieve the DISTINCT records from each column & populate them in drop-down lists that will be finally displayed to the user. For each column, there will be 1 drop-down list which will be listing the DISTINCT records of that column. For e.g. if there are, say, 15 columns, there will be 15 drop-down lists i.e. one drop-down for each column. Had I known the column names while coding, the following queries would have sufficed: SELECT DISTINCT(Col1) FROM MyTable ORDER BY Col1 SELECT DISTINCT(Col2) FROM MyTable ORDER BY Col2 SELECT DISTINCT(Col3) FROM MyTable ORDER BY Col3 ............. ............. but since the column names are not known, the above won't work in my case. I have to get the column names first. To do so, I am using the INFORMATION_SCHEMA.COLUMNS view in my stored procedure to first get the column names & then looping through the columns to get the DISTINCT records from each of the columns. This is code snippet in my stored procedure: ---------------------------------------- CREATE PROCEDURE GetRecords AS DECLARE @sql varchar(8000) WHILE (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='MyTable') IS NOT NULL BEGIN SET @sql='SELECT DISTINCT(COLUMN_NAME) FROM MyTable WHERE COLUMN_NAME IS NOT NULL ORDER BY COLUMN_NAME' END EXEC (@sql) ---------------------------------------- But when the above is executed in QA, as expected, it throws the "Subquery returned more than 1 value. This is not permitted......" error. So how do I get the column names & then retrieve the DISTINCT records from each column? Thanks, Arpan Try,
> WHILE (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE declare @ordinal_position int> TABLE_NAME='MyTable') IS NOT NULL declare @cn sysname set @ordinal_position = 1 while @ordinal_position <= (select count(*) from information_schema.columns where table_schema = 'dbo' and table_name = 'MyTable') begin select @cn = column_name from information_schema.columns where table_schema = 'dbo' and table_name = MyTable' and ordinal_position = @ordinal_position set @sql = 'SELECT DISTINCT(' + quotename(@cn) + ') FROM MyTable ORDER BY ' + quotename(@cn) exec sp_executesql @sql set @ordinal_postion = @ordinal_position + 1 end .... AMB Show quote "Arpan" wrote: > My application retrieves records from a SQL Server 7.0 DB table for > which I am using a stored procedure but while coding, I am not aware of > the no. of columns existing in that DB table. Neither am I aware of the > column names while coding. Also more columns can get added to the table > in the future. > > What I want to do is retrieve the DISTINCT records from each column & > populate them in drop-down lists that will be finally displayed to the > user. For each column, there will be 1 drop-down list which will be > listing the DISTINCT records of that column. For e.g. if there are, > say, 15 columns, there will be 15 drop-down lists i.e. one drop-down > for each column. Had I known the column names while coding, the > following queries would have sufficed: > > SELECT DISTINCT(Col1) FROM MyTable ORDER BY Col1 > SELECT DISTINCT(Col2) FROM MyTable ORDER BY Col2 > SELECT DISTINCT(Col3) FROM MyTable ORDER BY Col3 > ............. > ............. > > but since the column names are not known, the above won't work in my > case. I have to get the column names first. To do so, I am using the > INFORMATION_SCHEMA.COLUMNS view in my stored procedure to first get the > column names & then looping through the columns to get the DISTINCT > records from each of the columns. This is code snippet in my stored > procedure: > > ---------------------------------------- > CREATE PROCEDURE GetRecords > AS > DECLARE > @sql varchar(8000) > > WHILE (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE > TABLE_NAME='MyTable') IS NOT NULL > BEGIN > SET @sql='SELECT DISTINCT(COLUMN_NAME) FROM MyTable WHERE COLUMN_NAME > IS NOT NULL ORDER BY COLUMN_NAME' > END > EXEC (@sql) > ---------------------------------------- > > But when the above is executed in QA, as expected, it throws the > "Subquery returned more than 1 value. This is not permitted......" > error. > > So how do I get the column names & then retrieve the DISTINCT records > from each column? > > Thanks, > > Arpan > > The Curse and Blessings of Dynamic SQL
http://www.sommarskog.se/dynamic_sql.html AMB Show quote "Alejandro Mesa" wrote: > Try, > > > > WHILE (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE > > TABLE_NAME='MyTable') IS NOT NULL > > declare @ordinal_position int > declare @cn sysname > > set @ordinal_position = 1 > > while @ordinal_position <= (select count(*) from information_schema.columns > where table_schema = 'dbo' and table_name = 'MyTable') > begin > select > @cn = column_name > from > information_schema.columns > where > table_schema = 'dbo' and table_name = MyTable' > and ordinal_position = @ordinal_position > > set @sql = 'SELECT DISTINCT(' + quotename(@cn) + ') FROM MyTable ORDER BY > ' + quotename(@cn) > > exec sp_executesql @sql > > set @ordinal_postion = @ordinal_position + 1 > > end > ... > > > AMB > > "Arpan" wrote: > > > My application retrieves records from a SQL Server 7.0 DB table for > > which I am using a stored procedure but while coding, I am not aware of > > the no. of columns existing in that DB table. Neither am I aware of the > > column names while coding. Also more columns can get added to the table > > in the future. > > > > What I want to do is retrieve the DISTINCT records from each column & > > populate them in drop-down lists that will be finally displayed to the > > user. For each column, there will be 1 drop-down list which will be > > listing the DISTINCT records of that column. For e.g. if there are, > > say, 15 columns, there will be 15 drop-down lists i.e. one drop-down > > for each column. Had I known the column names while coding, the > > following queries would have sufficed: > > > > SELECT DISTINCT(Col1) FROM MyTable ORDER BY Col1 > > SELECT DISTINCT(Col2) FROM MyTable ORDER BY Col2 > > SELECT DISTINCT(Col3) FROM MyTable ORDER BY Col3 > > ............. > > ............. > > > > but since the column names are not known, the above won't work in my > > case. I have to get the column names first. To do so, I am using the > > INFORMATION_SCHEMA.COLUMNS view in my stored procedure to first get the > > column names & then looping through the columns to get the DISTINCT > > records from each of the columns. This is code snippet in my stored > > procedure: > > > > ---------------------------------------- > > CREATE PROCEDURE GetRecords > > AS > > DECLARE > > @sql varchar(8000) > > > > WHILE (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE > > TABLE_NAME='MyTable') IS NOT NULL > > BEGIN > > SET @sql='SELECT DISTINCT(COLUMN_NAME) FROM MyTable WHERE COLUMN_NAME > > IS NOT NULL ORDER BY COLUMN_NAME' > > END > > EXEC (@sql) > > ---------------------------------------- > > > > But when the above is executed in QA, as expected, it throws the > > "Subquery returned more than 1 value. This is not permitted......" > > error. > > > > So how do I get the column names & then retrieve the DISTINCT records > > from each column? > > > > Thanks, > > > > Arpan > > > > Thanks, Alejandro, for your suggestion. The procedure, as such, works
fine but the only hitch is all the records are returned in one single column, something like this (in QA): Col1 ----------------- Rec1 Rec2 Rec3 Rec4 Rec5 Col2 ---------------- Rec1 Rec3 Rec4 Col3 ---------------- Rec2 Rec4 Rec5 How do I display the records in the conventional manner like this: Col1 Col2 Col3 ----- ----- ----- Rec1 Rec1 Rec2 Rec2 Rec3 Rec4 Rec3 Rec4 Rec5 Rec4 Rec5 Thanks once again, Regards, Arpan > I am not aware of Ouch. I wouldn't want to be in your shoes. The first thing to ask yourself is who designed this, and > the no. of columns existing in that DB table. Neither am I aware of the > column names while coding. Also more columns can get added to the table > in the future. why and if you need to live with it... As for your code, the SELECT in the while loop is no way connected to the first SELECT. You can do this using a cursor, though: USE pubs GO CREATE PROCEDURE GetRecords AS SET NOCOUNT ON DECLARE @col sysname, @sql varchar(8000) DECLARE c CURSOR FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='authors' OPEN c FETCH NEXT FROM c INTO @col WHILE @@FETCH_STATUS = 0 BEGIN SET @sql='SELECT DISTINCT ' + @col + ' FROM authors WHERE ' + @col + ' IS NOT NULL ORDER BY ' + @col + '' --PRINT @sql EXEC (@sql) FETCH NEXT FROM c INTO @col END CLOSE c DEALLOCATE c -- Show quoteTibor Karaszi, SQL Server MVP http://www.karaszi.com/sqlserver/default.asp http://www.solidqualitylearning.com/ Blog: http://solidqualitylearning.com/blogs/tibor/ "Arpan" <arpan***@hotmail.com> wrote in message news:1128025951.296851.198910@g43g2000cwa.googlegroups.com... > My application retrieves records from a SQL Server 7.0 DB table for > which I am using a stored procedure but while coding, I am not aware of > the no. of columns existing in that DB table. Neither am I aware of the > column names while coding. Also more columns can get added to the table > in the future. > > What I want to do is retrieve the DISTINCT records from each column & > populate them in drop-down lists that will be finally displayed to the > user. For each column, there will be 1 drop-down list which will be > listing the DISTINCT records of that column. For e.g. if there are, > say, 15 columns, there will be 15 drop-down lists i.e. one drop-down > for each column. Had I known the column names while coding, the > following queries would have sufficed: > > SELECT DISTINCT(Col1) FROM MyTable ORDER BY Col1 > SELECT DISTINCT(Col2) FROM MyTable ORDER BY Col2 > SELECT DISTINCT(Col3) FROM MyTable ORDER BY Col3 > ............ > ............ > > but since the column names are not known, the above won't work in my > case. I have to get the column names first. To do so, I am using the > INFORMATION_SCHEMA.COLUMNS view in my stored procedure to first get the > column names & then looping through the columns to get the DISTINCT > records from each of the columns. This is code snippet in my stored > procedure: > > ---------------------------------------- > CREATE PROCEDURE GetRecords > AS > DECLARE > @sql varchar(8000) > > WHILE (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE > TABLE_NAME='MyTable') IS NOT NULL > BEGIN > SET @sql='SELECT DISTINCT(COLUMN_NAME) FROM MyTable WHERE COLUMN_NAME > IS NOT NULL ORDER BY COLUMN_NAME' > END > EXEC (@sql) > ---------------------------------------- > > But when the above is executed in QA, as expected, it throws the > "Subquery returned more than 1 value. This is not permitted......" > error. > > So how do I get the column names & then retrieve the DISTINCT records > from each column? > > Thanks, > > Arpan > Thanks, Tibor, for your suggestion.
Yeah....you are right.....the DB table has indeed been designed very poorly by someone who doesn't know anything about designing DB tables & DB programming but due to paucity of time, he wants me to adhere to that DB only. Actually the DB table has been imported from a MS-Excel file. BTW, is adding columns to a DB table, dynamically or manually, after that table has been in use for a considerable period of time a bad practice? Why doesn't EXEC (@sql) in your procedure generate any resultset? Thanks once again, Regards, Arpan > Why doesn't EXEC (@sql) in your procedure generate any resultset? Strange... when I execute the GetRecords procedure in the pubs database, from Query Analyzer, I get a number of resultsets back... > BTW, is adding columns to a DB table, dynamically or manually, after Things in the organization might change, to DDL changes can be required, often with a new version of > that table has been in use for a considerable period of time a bad > practice? the software. Frequent DDL changes can be, IMO, a less than perfect datamodel. Possibly not normalized. -- Show quoteTibor Karaszi, SQL Server MVP http://www.karaszi.com/sqlserver/default.asp http://www.solidqualitylearning.com/ Blog: http://solidqualitylearning.com/blogs/tibor/ "Arpan" <arpan***@hotmail.com> wrote in message news:1128040629.262128.211750@g43g2000cwa.googlegroups.com... > Thanks, Tibor, for your suggestion. > > Yeah....you are right.....the DB table has indeed been designed very > poorly by someone who doesn't know anything about designing DB tables & > DB programming but due to paucity of time, he wants me to adhere to > that DB only. Actually the DB table has been imported from a MS-Excel > file. > > BTW, is adding columns to a DB table, dynamically or manually, after > that table has been in use for a considerable period of time a bad > practice? > > Why doesn't EXEC (@sql) in your procedure generate any resultset? > > Thanks once again, > > Regards, > > Arpan > I am sorry Tibor.....there was a typo in the stored procedure due to
which no resultset was generated. The typo was in FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='MyTable' ORDER BY ORDINAL_POSITION line. I had coded it as FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='MyTable ORDER BY ORDINAL_POSITION' but stangely enough, neither the procedure generated any error while compiling nor were any errors generated when the procedure was executed in QA. Why so? Is it because the compiler presumed the table name to be 'MyTable ORDER BY ORDINAL_POSITION'? If so, then shouldn't the compiler have generated the "Invalid object name" error since no such table exists in the DB? Another question that has been coming to my mind after going through your code & Alejandro's code is it is said that, if I am not mistaken, using cursors should be avoided as far as possible in DB programming. Using dynamic SQL queries also has its drawbacks; so how does an amateur (like me!) understand when to use cursors & when to use dynamic SQL? Thanks, Regards, Arpan On 30 Sep 2005 21:08:03 -0700, Arpan wrote:
Show quote >I am sorry Tibor.....there was a typo in the stored procedure due to Hi Arpan,>which no resultset was generated. The typo was in > >FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE >TABLE_NAME='MyTable' ORDER BY ORDINAL_POSITION > >line. I had coded it as > >FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE >TABLE_NAME='MyTable ORDER BY ORDINAL_POSITION' > >but stangely enough, neither the procedure generated any error while >compiling nor were any errors generated when the procedure was executed >in QA. Why so? Is it because the compiler presumed the table name to be >'MyTable ORDER BY ORDINAL_POSITION'? If so, then shouldn't the compiler >have generated the "Invalid object name" error since no such table >exists in the DB? The compiler simply produced a plan to find all rows in the INFORMATION_SCHEMA.COLUMNS view for a table named 'MyTable ORDER BY ORDINAL_POSITION'. That in itself is a valid query. (And in fact - if you really want it, you CAN have a table with that name!!) When you execute the procedure and open the cursor, it turns out that there are no columns in a table with that name. As a result, the first FETCH from the cursor will result in FETCH_STATUS <> 0 and the code in the WHILE loop will never execute. >Another question that has been coming to my mind after going through The real answer is that you shouldn't be using cursors and dynamic sql.>your code & Alejandro's code is it is said that, if I am not mistaken, >using cursors should be avoided as far as possible in DB programming. >Using dynamic SQL queries also has its drawbacks; so how does an >amateur (like me!) understand when to use cursors & when to use dynamic >SQL? You should be busy redesigning your model. Or rather - that's what you should be doing if you inherited it. If you designed it yourself, you should be attending a crash course on data modelling, and THEN go for the redesign. But we all know that sometimes you are stuck with a bad model and you need to get some data from it NOW and can only fix the real problem later. Best, Hugo -- (Remove _NO_ and _SPAM_ to get my e-mail address) |
|||||||||||||||||||||||