T-SQL, Cursors, FETCH INTO. How to use SELECT * - sql

I am building a one off query to iterate through a set of joined tables. The select statement is using "SELECT *". Since it's is a table with lots of fields, I don't want to specify each column as a variable. Is there a way to FETCH INTO an array or SET of some sort and just grab the values I want?

Apparently not:
INTO #variable_name[ ,...n]
"Allows data from the columns of a fetch to be placed into local variables.
Each variable in the list, from left to right, is associated with the corresponding column in the cursor result set. The data type of each variable must either match or be a supported implicit conversion of the data type of the corresponding result set column. The number of variables must match the number of columns in the cursor select list."
If you are looking to use cursors you may find better flexibility with CLR Stored procedures

Even if there was, you wouldn't want to. Fetching extra fields is one of the most common causes of performance degredation in a SQL Server application. By doing so, you restrict the optimizer's ability to use indexes effectively.
How would you propose to "grab the values that you want" without specifying column names?

Why do you need to use a cursor? Those are frowned upon in SQL Server scenarios - most of the time, they're unnecessary, and usually they're very slow and hurt performance.
What are you trying to accomplish with your cursor? Couldn't you do it in a set-based manner and use SQL Server's abilities to the max??
Marc

In 2k5 (SQL 2000 has different system objects), use the SQL metadata to quickly write queries with long lists of table/column names:
SELECT
O.Name + '__' + C.Name + ' = ' + O.Name + '.' + C.Name + ','
FROM Sys.Objects O
JOIN Sys.Columns C
ON C.Object_Id = O.Object_Id
WHERE O.Name IN ('Table1', 'Table1')
ORDER BY O.Name, C.Column_Id
I'm not sure exactly what you're trying to do with the result set, but this might be a decent start.
Also, you could declare variables as SQL_VARIANT and FETCH result sets into them like this:
DECLARE #Col1 SQL_VARIANT
SELECT #Col1 = Table1.Column1 FROM Table1
PRINT CONVERT(varchar(max), #Col1)
I'm not sure what that gains you though.

This is being suggested only for those that work with SQL daily, not specifically to answer this question.
The RedGate product SQL Prompt has the ability to expand wild-card characters into individual field names by using short-cut keys (Ctrl-B, Ctrl-W). This can save you alot of time and make it easier to remove a few fields from the query for those occasions where you do need most of them.

In SQL2005 you could also right-click the table an choose open table. Then you click the little SQL-Icon and you see the select statement, something like select * from YourTable. Clicking again on the !-icon the select * from will be expanded to the full fieldlist.
Good luck.

Related

Find out all useful columns in a table in sql server

I have a table which has 50+ columns but only few columns are getting used. that means when any stored procedure uses that table it only refers 4-5 columns in select/where statements . rest of columns are not getting used . i just want to list down those columns that are actually getting used. one way is finding out the dependencies of a table and then go through every SP and find out which columns are getting used . but in that case i have around 30+ Sp. is there any efficient way to do it.
To use multiple columns in a procedure, you can use a code like below
create procedure sp_sample
#column_names varchar(200)
as
if #column_names='' or #column_nams is null
set #column_names='*'
exec ('select '+#column_name +' from table')
Here are some examples :
exec sp_sample #columnname='id,name'
or
exec sp_sample #columnname='id,name,telphone'
Try this:
select name from syscomments c
join sysobjects o on c.id = o.id
where TEXT like '%table_name%' and TEXT like '%column_name%'
In table_name give you table name, in column_name give the column for which you want to chck the procedure dependencies.You will get the stored procedure names as output
If you import your database as a database project using the SQL Server Data Tools, you will be able to find all references to a table or column using the "Find All References" context command. What makes this particularly useful is the accuracy: it will even find instances of SELECT * that don't mention the column explicitly, but implicitly refer to it anyway. It will also not be confused by tables or columns with similar names (finding particular instances of ID is otherwise rather problematic).
If all you want to know if a column is referenced at all, you can simply delete it and see if any "unresolved reference" errors appear in the error list -- if yes, then the column is used somewhere.

SQL Question checking nulls

I'm very new to sql. I am on this project where I have to check if something is null and if it is I have to change it to zero but there are many tables that I would have to do this and many columns. I was wondering if there was a way that I can check the whole table for nulls instead of checking every column of every table.
Michelle, no you need to check every column for NULLS. The bigger question is why are NULLS being allowed? While I'm not an advocate for never having NULLS in a database (I believe that they have their purpose), an excessive number of NULL values in a table is a good indicator that the database is not normalized properly or has other architectural issues.
It does depend on the platform, but in some cases you can use the system table information to get a list of all of the columns, and utilise this to generate queries to verify every column in every table.
However, that would be quite a hack. The real questions are a) why are there so many nulls ( there might be good reasons, but it does suggest that the structure is wrong, as per Wil ) and b) why is there a sudden need to change then all to zeros? Does this only apply to numeric fields? There are so many other questions that you need to ask before a clear solution becomes clear.
You say you have to change any NULL values to 0, so perhaps the easiest way would be to use COALESCE(value, 0).
COALESCE(value, value2, value3) is a shortcut to a CASE statement like
CASE
WHEN value1 IS NOT NULL THEN value1
WHEN value2 IS NOT NULL THEN value2
...
END
Edit:
If you actually want to update all NULLS to 0 on the table, you could do the following SQL statement:
SELECT 'UPDATE '
+ OBJECT_NAME(OBJECT_ID)
+ ' SET '
+ sc.name
+ ' = 0 WHERE '
+ sc.name
+ ' IS NULL'
FROM sys.columns sc
INNER JOIN sys.types st ON st.system_type_id = sc.system_type_id
WHERE st.name IN ('bigint', 'int', 'smallint')
AND OBJECT_NAME(OBJECT_ID) = 'YourTable'
Which will product a text string that you should be able to copy and paste and run, or run programatically in a loop. It depends on your columns having a number data type, and could be dangerous if you have any such columns whose NULLs you actually want to stay as null. You could take out that last part of the WHERE clause to run it for all tables, but you may want to test and validate beforehand.
I don't have a SQL Server instance at the ready to test on, so this comes with the generic "use at your own risk" disclaimer. :-)
Select nvl(col,'0') from table ;
NVL will work fine in oracle.
NVL will check if col is null, if it is null it will change it to zero.

SQL Server 2008 column select

In SQL Server, if I got a table with like 20 columns and I want 18 of them, can I say something like * minus columnname1, columnname2, course right now I write them all.
But if you could it would be much easier.
Little hint to replace the asterisk with column names in SQL Management Studio in no time without any fancy plugin:
Select your written query (no matter how many joins, etc.)
Right click and select "Design Query in Editor..."
Simply click "Ok"
The asterisk should have been expanded to column names now :)
Ofc it's possible to select/deselect any column in the query editor..
Hth
It is not possible. However if you are using SQL Server Management Studio 2008 / 2005 you can right click on the table and select the "Script Table as > SELECT To" menu option. This will save you typing the column names, or purchase Red-Gate's SQL Prompt
Out of the box - no, it's not possible. You have to spell out all the columns you want explicitly.
With SQL Server Management Studio 2008, there is intellisense which can help you select columns from a table - so that's certainly one step to help ease the pain.
Add-in tools like SQL Prompt offer more help - in SQL Prompt, you can type
SELECT *
FROM dbo.YourTable
and if you have the cursor just after the asterisk symbol (*), you can press <TAB> and expand the asterisk into the list of all columns for that table (and then remove the two you don't want) - or you can popup a window and pick those columns you really want.
Very handy, very useful, very much speeding up development - but it's not a free tool.....
You can use select TOP (18) * from givenTable is you want 18 rows.
There is no such method for columns. In fact column names are stored in master db and you can extract them and consruct query looking like what you are asking for BUT it would not be easier than just select field1,field2 ... field18 from blaBlaBla.
SELECT table_name=sysobjects.name,
column_name=syscolumns.name,
datatype=systypes.name,
length=syscolumns.length
FROM sysobjects
JOIN syscolumns ON sysobjects.id = syscolumns.id
JOIN systypes ON syscolumns.xtype=systypes.xtype
WHERE sysobjects.xtype='U'
and sysobjects.name='myTableName'
ORDER BY sysobjects.name,syscolumns.colid
will give you the list of your columns. You can write select generator based on this query.
I'd like to add to the answer of, "No, it's not possible directly in SQL". I would love to have that feature too! It sucks when you're trying to do some quick debugging on a 10+ column table that has a varbinary(max).
But I really just want to point out an alternative to Kane's tip for SSMS 2008 (Sql Server Management Studio).
If you open the Object Explorer (right-click in the query window and choose "Open Server in Object Explorer"), navigate to the node for the table in question. Expand the node so you can see the "Columns" node. Now "drag" the Columns node over to your query window and "drop" it. It will paste in all the column names for the table--and you can use it directly in a SELECT clause.
It is not possible as far as I know.
I have created a script for easy copy/pasting multiple columns, you might find it useful. See:
http://www.sqlservercentral.com/scripts/102375/
The script is explained in detail there, but in short for those who do not have an account on sqlservercentral:
It's a stored procedure that i can run using a shortcut. Type in your tablename (also works with temp tables and views), highlight it, hit the shortcut and it will display the columns of the table. From there you can easily copy multiple columns (the columns are also shown with a comma in front of the column name, so that also saves you some typing) and paste it in your query screen.
CREATE PROCEDURE [dbo].[sp_ColumnSelect]
#FullObjectName varchar(200)
AS
/*
Author: Robin van Schaik
Version: 1.3 (03-OCT-2012)
*/
DECLARE #Object varchar(200)
DECLARE #Schema varchar(200)
DECLARE #Database varchar(200)
DECLARE #IsTempTable bit
-- Break down parameter in Database/Schema/Object
SET #Object = PARSENAME(#FullObjectName,1)
SET #Schema = ISNULL(PARSENAME(#FullObjectName,2),'dbo')
SET #IsTempTable = case when left(#Object,1)='#' then 1 else 0 end
SET #Database = case when #IsTempTable=1 then 'tempdb' else PARSENAME(#FullObjectName,3) end
EXEC(
'SELECT
b.Name as ColumnStart
, '',''+b.Name as ColumnNext
, ''[''+b.Name+'']'' as ColumnStartBr
, '',[''+b.Name+'']'' as ColumnNextBr
FROM
' +#Database+'.sys.objects a
INNER JOIN
' +#Database+'.sys.columns b
ON a.object_id=b.object_id
INNER JOIN
' +#Database+'.sys.schemas d
ON a.schema_id=d.schema_id
WHERE
a.Object_ID=OBJECT_ID('''+#Database+'.'+#Schema+'.'+#Object+''')
AND d.name = '''+#Schema+'''
'
)

How can I turn a column name into a result value in SQL Server?

I have a table which has essentially boolean values in a legacy database. The column names are stored as string values in another table so I need to match the column names of one table to a string value in another table. I know there has to be a way to do this directly with SQL in SQL Server but it is beyond me.
My initial thought was to use PIVOT but it is not enabled by default and enabling it would likely be a difficult process with pushing that change to the Production database. I would prefer to use what is enabled by default.
I am considering using COALESCE to translate the boolean value to the string that value that I need. This will be a manual process.
I think I will also use a table variable to insert the results of the first query into that variable and use those results to do the second query. I still have the problem that the columns are on a single row so I wish I could easily pivot the values to put the column names in the result set as strings. But if I could easily do that I could easily write the query with a sub-select.
Any tips are welcome.
Checkout Sysobjects and SysColumns in SQL Server. They are 2 SQL tables that gives you the names of the tables in your DB and the names of the columns that go with that table.
The system view INFORMATION_SCHEMA.COLUMNS will also give you what you want.
You can build a SQL string and then execute that string as a query. Not the prettiest by any means but I think it would work the way you want it to. You would just use a cursor or while loop to build the string.
If you're comfortable with .Net you could just write your own stored proc in your language of choice and manipulate the data in code instead.
Heres a link to get started
CLR Stored Procedures
I'm not quite sure I understand how your design is currently put together (could you post an example?), but the information_schema.columns view will give you a table containing all the column names as string values. If you join your second table against that I think you'll probably get what you need.
For Example, i have a table STATEtbl having 3 columns and i want to get all the column names of this table as ROW values... i use the below query
Select SC.name as Columns from Syscolumns SC
Join Sysobjects SO On SC.id = SO.Id
where Object_name(SO.Id) = 'STATEtbl'
Result of the query:
Columns
--------
State
StateCode
StateFullName

Fastest way to loop thru a SQL Query

What is the fastest way to loop thru a Query in T-SQL .
1) Cursors or
2) Temp tables with Key added or
any thing else.
The fastest way to "loop" thru a query is to just not do it. In SQL, you should be thinking set-based instead of loop-based. You should probably evaluate your query, ask why you need to loop, and look for ways to do it as a set.
With that said, using the FAST_FORWARD option on your cursors will help speed things along.
For your stated goal, something like this is actually a better bet - avoids the "looping" issue entirely.
declare #table table
(
ID int
)
insert into #table select 1 union select 2 union select 3 union select 4 union select 5
declare #concat varchar(256)
-- Add comma if it is not the first item in the list
select #concat = isnull(#concat + ', ', '') + ltrim(rtrim(str(ID))) from #table order by ID desc
-- or do whatever you want with the concatenated value now...
print #concat
Depends on what you're trying to do. Some tasks are better suited for cursors, some for temp tables. That's why they both exist.
I don't think you need a cursor for that (your comment about concat) if I understand what you're going for.
Here's one of mine that grabs all the phone numbers for a contact and plops them in a field and returns it.
DECLARE #numbers VARCHAR(255)
SELECT #numbers = COALESCE(#numbers + ' | ','') + PHONE_NUMB FROM my_table (NOLOCK)
WHERE CONTACT_ID=#contact_id RETURN #numbers
Cursors are usually resource hogs especially as your table size grows. So if your table size is small I would be okay with recommending a cursor, however, a larger table would probably do better with an external or temporary table.
Do you want to loop through query output inside stored procedure OR from C# code?
Generally speaking, you should avoid looping through query output one row at a time. SQL is meant for set based operations so see if you can solve your problem using set based approach.
Depending on the size of your result set - Table variables are in memory and require no disk read, can be treated just like a table (set operations) and are very fast until result set gets to large for memory (which then requires swap file writes).
Here's a shortcut to get a comma-delimited string of a single field from a query that returns a number of rows. Pretty quick compared to the alternatives of cursors, etc., and it can be part of a subquery (i.e., get some things, and in one column, the ids of all the things related to each thing in some other table):
SELECT
COALESCE(
REPLACE(
REPLACE(
REPLACE(
(SELECT MyField AS 'c' FROM [mytable] FOR XML PATH('')),'</c><c>',','),
'<c>',''),
'</c>',''),
'')
AS MyFieldCSV
Caveat: it won't play nice if your column contains characters that FOR XML PATH will escape.
Cursor is not good avoid cursor and use while loop in place of cursor
Temp table with key added is the best way to use looping.
i have to manipulate more than 1000000 rows in the table and
for cursor take 2 min because of complex logic.
but when convert cursor in to while loop it will take
25 seconds only. so that's big diffrence in performace.