I'm doing a basic query where I'm doing
Select Lower(column-name) from table
Now if I want to do a lower case on more than one column, I would need to do a
Select Lower(col1), Lower(col2) from table
I wanted to know if it's possible to do lowercase function application on all columns.
Something like
Select Lower(*) from table
This is not a valid statement, when I'm trying on sqlite3 and I'm guessing it's same for other vendors too. Has anybody been able to do this via a different approach. PL/SQL or T-SQL maybe.
No. It isnt possible to fetch all columns in lower case all at once.
I concur that there is no way to do this without mentioning each column. But since your consuming application will presumably have to loop through all columns and rows anyway, I suggest that is the right place to transform this data anyway...
While its not possible to use an inbuilt sql construct to achieve this, yet a small sql script should solve the purpose. Please consider the script given below:
declare #number_of_columns int
declare #counter int
declare #query nvarchar(max)
declare #column_name nvarchar(max)
set #query = 'select '
set #counter = 1
select #number_of_columns = count(ordinal_position) from information_schema.columns where table_name = '<your table name>'
while(#counter <= #number_of_columns)
begin
select #column_name = column_name from information_schema.columns
where table_name = '<your table name>' and ordinal_position = #counter
if(#counter < #number_of_columns)
begin
Set #query = #query + 'lower(' + (#column_name) + '),'
end
else
begin
Set #query = #query + 'lower(' + (#column_name) + ')'
end
set #counter = #counter + 1
end
set #query = #query + ' from <your table name>'
select #query
EXEC sp_executesql #query = #query
While, the above script would not work for 'ntext' data type implicitly as its explicit conversion to varchar is required to apply 'lower' function, also the script might not be required for data types like 'int','datetime' etc. So modify the script by applying additional conditions on the data types of the columns.
Related
I have a SELECT statement that can produce a list of values:
DECLARE #ValueList varchar(Max);
SELECT #ValueList = COALESCE(#ValueList + ',', '') + CAST(Val AS varchar(max))
FROM
(SELECT TOP (100) PERCENT tblSampleTable.SomeIDNumber AS Val
FROM tblSampleTable) AS ValuesThisYear
PRINT #ValList
This returns a list with values something like
val1,val2,val4,val9,
etc., ehich I can then feed into a stored procedure, or manage some other way.
Now I want to have the query that gets assessed for the list of values to be dynamic, maybe passed in or from another stored procedure, similar to this:
DECLARE #ValueList varchar(Max);
DECLARE #TSQL varchar(Max);
SET #TSQL = {stored proc to get base query}
SELECT #ValueList = COALESCE(#ValueList + ',', '') + CAST(Val AS varchar(max))
FROM
(#TSQL) AS ValuesThisYear
PRINT #ValList
I know that's the wrong syntax for including #TSQL, and that's what I'm trying to find out. I've viewed a number of threads and tried a number of methods, but am still not able to incorporate this dynamic part.
The tricky part seems to be the making of the list (the COALESCE and CAST statements), where I incorporate #ValList as part of the returned string.
Any help would be appreciated!
Dynamic SQL is usually about
Creating a variable that contains the exact SQL you want to run
Then using EXEC (#SQLvariable) to run that code
For example (not for production yet!) I've added a new variable #CustomSQL
DECLARE #ValueList varchar(Max);
DECLARE #TSQL varchar(Max);
DECLARE #CustomSQL varchar(Max);
SET #TSQL = {stored proc to get base query}
SET #CustomSQL =
'SELECT COALESCE(#ValueList + '','', '''') + CAST(Val AS varchar(max))
FROM (
' + #TSQL + '
) As ValuesThisYear;'
PRINT #CustomSQL
EXEC (#CustomSQL)
Notice that adding text/strings (e.g., the #TSQL variable) have to be entered as exact strings rather than their variable names. Also note apostrophes - you need to use '' every time you wish to refer to a '.
I also removed the variable name from the SELECT #ValueList = ... because the dynamic SQL cannot actually reference the variables - it has its own scope (?cannot remember the correct word) and doesn't have access to the variables. Solutions to this include
Using a temporary table e.g., #temp which can be referenced
Using the OUTPUT clause
Personally, I would approach it a different way - use the T-Sql provided to put data into a temporary table. Then use the temporary table in the other statement e.g.,
DECLARE #ValueList varchar(Max);
DECLARE #TSQL varchar(Max);
SET #TSQL = {stored proc to get base query}
DECLARE #CustomSQL varchar(Max)
CREATE TABLE #temp (Val varchar(1000))
SET #CustomSQL = 'INSERT INTO #temp (Val) ' + #TSQL
EXEC (#CustomSQL)
SELECT #ValueList = COALESCE(#ValueList + ',', '') + CAST(Val AS varchar(max))
FROM #temp As ValuesThisYear;
PRINT #ValList
I almost never get my dynamic SQL correct first try. Suggestions
Keep it as simple as possible
Before having a version that runs (e.g., EXEC (#CustomSQL)), comment the EXEC out and PRINT it instead.
Here are some examples from previous posts I've done recently
Query for R Machine Learning Services - Filtering Categories in Where Clause
Bottom of Dynamic columns depend on previous dynamic columns - TSQL
I am a beginner in Dynamic SQL and trying to write a dynamic sql code in which I need to include a table variable .When I try to include the table variable I am getting an error saying that I need to include the Static variable.
Below is just part of the code
DECLARE #NAMES TABLE (name varchar)
DECLARE #fields varchar(max);
.
.
.
Select #fields=FROM sys.columns
WHERE object_id=object_id('dbo.employees')
order by name
SET #SQL=''
SET #SQL='Select '+ #fields
SET #SQL=#SQL + ' from dbo.test()'
SET #SQL = #SQL + ' WHERE name IN'
SET #SQL= #SQL + '(Select name from '
SET #SQL=#SQL + #NAMES +')'
To start with, your SELECT to get the column names won't work at all. You need something like this:
DECLARE #fields nvarchar(max);
SET #fields = N'';
SELECT #fields += CASE WHEN LEN(#fields) = 0 THEN N'' ELSE N', ' END + name
FROM sys.columns
WHERE object_id=object_id('dbo.employees')
ORDER BY column_id
PRINT #fields;
I'm honestly not sure what the rest of your SQL is trying to do... it's trying to select the fields from the employee table from the return of a table-valued function called test()? Where the 'name' column from that test() result set is in ... what? You'll need to be a lot more clear before I can give you a complete answer. One major problem is that you've never actually filled your table variable with anything, so ... I have no idea what you're going for. Knowing the definition of the Test() function would also be helpful.
But at least the above will give you the #fields variable set correctly to the list of columns in the table dbo.employee.
When doing Dynamic SQL, it really helps to write out the end resulting SQL you want, and then identify what parts of that SQL should be filled in by variable data, and work backwards. It's then a lot easier to construct your SQL to build your dynamic SQL.
You need to include the tablevariable logic to dynamic sql
--You need to load #names inside dynamic sql
DECLARE #fields varchar(max);
.
.
.
Select #fields=FROM sys.columns
WHERE object_id=object_id('dbo.employees')
order by name
SET #SQL='DECLARE #NAMES TABLE (name varchar); '
SET #SQL +=' Select '+ #fields
SET #SQL=#SQL + ' from dbo.test()'
SET #SQL = #SQL + ' WHERE name IN'
SET #SQL= #SQL + '(Select name from '
SET #SQL=#SQL + ' #NAMES )'
Or you can load into temp table and access the temptable inside dynamic sql. This means you will be loading temptable like #names and then use that in dynamic sql...
My application runs over several databases, and it needs to be able to check from one to see if a column exists in the other. Unfortunately, I won't know the name of the second database until runtime, so it needs to be dynamic. Also, it has to do this in multiple places, so ideally I'd like to make it into a function, but this gives me problems because functions won't run dynamic SQL.
This is the (non-working) function I wrote.....
CREATE FUNCTION [dbo].[fn_checkcolexists] (
#dbname VARCHAR(100)
,#tablename VARCHAR(100)
,#colname VARCHAR(100)
)
RETURNS BIT
AS
BEGIN
DECLARE #sqlstring NVARCHAR(2000)
SET #sqlstring = 'select #retVal = 1 from ' + #dbname + '.sys.columns cols inner join yodata_dev_load.sys.tables tabs
on cols.object_ID=tabs.object_ID where cols.name=''' + #colname + ''' and tabs.name=''' + #tablename + ''''
DECLARE #retVal INT
EXEC sp_executesql #sqlstring
,N'#retVal int output'
,#retVal OUTPUT
RETURN #retval
END
Has anyone got any suggestions how I can accomplish this? I can't find a way to access the column information for every database. Does this information exist in the system databases anywhere?
Alternatively, can I create some sort of synonym for the other database?
Edit: How to find column names for all tables in all databases in SQL Server isn't an ideal solution, because it also relies on dynamic SQL, so I couldn't use this as a function
Use stored procedure and use one of these
One of the methods is to use undocumented
EXEC sp_msforeachdb 'SELECT table_catalog FROM ?.INFORMATION_SCHEMA.COLUMNS
where table_name=''your_table'' and column_name=''your_column_name'''
or simulate it
declare #sql varchar(max), #table_name varchar(100)
select #sql='', #table_name='your_table'
select #sql=#sql+ 'SELECT table_catalog
FROM '+name+'.INFORMATION_SCHEMA.TABLES
where table_name='''+#table_name+''' and
column_name=''your_column_name''' from sys.databases
exec(#sql)
I think I've got the solution I was after. I am using COL_LENGTH, which seems to do the job. You can specify a dbname to is, and even pass that as a parameter, and it returns a null if the column does not exist.
eg
declare #dbname varchar(200)='dbname'
select COL_LENGTH(#dbname + '.dbo.tablename','columnname')
if this returns a null, the column doesn't exist
Many thanks for all the contributors to this thread
Hope this works for you
CREATE FUNCTION [dbo].[fn_checkcolexists]
(
#dbname VARCHAR(100)
,#tablename VARCHAR(100)
,#colname VARCHAR(100)
)
RETURNS INT
AS
BEGIN
DECLARE #RECCOUNT INT = 0
SELECT #RECCOUNT = COUNT(*) FROM information_schema.columns WHERE TABLE_CATALOG = #dbname AND COLUMN_NAME = #colname AND TABLE_NAME = #tablename
RETURN #RECCOUNT
END
GO
For a bit of database-sanity checking code, I'd like to determine whether a particular object_id corresponds to an empty table.
Is there some way to (for instance) select count(*) from magic_operator(my_object_id) or similar?
I'd strongly prefer a pure-sql solution that can run on MS SQL server 2008b.
You can get a rough idea from
SELECT SUM(rows)
FROM sys.partitions p
WHERE index_id < 2 and p.object_id=#my_object_id
If you want guaranteed accuracy you would need to construct and execute a dynamic SQL string containing the two part object name. Example below though depending on how you are using this you may prefer to use sp_executesql and return the result as an output parameter instead.
DECLARE #DynSQL nvarchar(max) =
N'SELECT CASE WHEN EXISTS(SELECT * FROM ' +
QUOTENAME(OBJECT_SCHEMA_NAME(#my_object_id)) + '.' +
QUOTENAME(OBJECT_NAME(#my_object_id)) +
') THEN 0 ELSE 1 END AS IsEmpty'
EXECUTE (#DynSQL)
Well it depends on what do you consider as Pure sql
I've come up with the following solution. It is purely written in T-SQL but uses dynamically built query
-- Using variables just for better readability.
DECLARE #Name NVARCHAR(4000)
DECLARE #Schema NVARCHAR(4000)
DECLARE #Query NVARCHAR(4000)
-- Get the relevant data
SET #Schema = QUOTENAME(OBJECT_SCHEMA_NAME(613577224))
SET #Name = QUOTENAME(OBJECT_NAME(613577224))
-- Build query taking into consideration the schema and possible poor object naming
SET #Query = 'SELECT COUNT(*) FROM ' + #Schema + '.' + #Name + ''
-- execute it.
EXEC(#Query)
EDIT
The changes consider the possible faulty cases described in the comments.
I've outlined the variables, because this is a convenient approach for me. Cheers.
I hope to find a way to get the value in the Nth column of a dataset.
Thus, for N = 6 I want
SELECT (Column6Value) from MyTable where MyTable.RowID = 14
Is there a way to do this in TSQL as implemented in SQL Server 2005? Thanks.
You should be able to join with the system catalog (Information_Schema.Columns) to get the column number.
This works:
create table test (a int, b int, c int)
insert test values(1,2,3)
declare #column_number int
set #column_number = 2
declare #query varchar(8000)
select #query = COLUMN_NAME from information_Schema.Columns
where TABLE_NAME = 'test' and ORDINAL_POSITION = #column_number
set #query = 'select ' + #query + ' from test'
exec(#query)
But why you would ever do something like this is beyond me, what problem are you trying to solve?
Not sure if you're at liberty to redesign the table, but if the ordinal position of the column is significant, your data is not normalized and you're going to have to jump through lots of hoops for many common tasks.
Instead of having table MyTable with Column1... ColumnN you'd have a child table of those values you formerly stored in Column1...ColumnN each in their own row.
For those times when you really need those values in a single row, you could then do a PIVOT: Link
Edit: My suggestion is somewhat moot. Ash clarified that it's "de-normalization by design, it's a pivot model where each row can contain one of any four data types." Yeah, that kind of design can be cumbersome when you normalize it.
If you know the range of n you could use a case statement
Select Case when #n = 1 then Column1Value when #n = 2 then Column2Value end
from MyTable
As far as I know there is no dynamic way to replace a column (or table) in a select statement without resorting to dynamic sql (in which chase you should probably refactor anyways)
Implementation of #Mike Sharek's answer.
Declare #columnName varchar(255),
#tablename varchar(255), #columnNumber int, #SQL nvarchar(4000)
Set #tablename = 'MyTable'
Set #columnNumber = 6
Select #columnName = Column_Name from Information_SChema.columns
where Ordinal_position = #columnNumber and Table_Name = #tablename
Set #SQL = 'select ' + #columnName + ' from ' + #tableName + ' where RowID=14'
Exec sp_Executesql #SQL
I agree with Sambo - why are you trying to do this? If you are calling the code from C# or VB, its much easier to grab the 6th column from a resultset.