Add a prefix to each column - sql

I have this table with this as name of the columns :
Name, Birthday, Year, Size
And I want to add a prefix to every column like this:
NY_Name, NY_Birthday, NY_Year, NY_Size
Obviously I have more columns than these 4, so this is the reason why I ask you for a query - how to add a prefix to column names with SQL Server?
Thank you very much ! :)

One idea is to generate a script from the table catalog (SELECT name FROM sys.objects WHERE type = 'U'), using the following procedure sp_rename (Transact-SQL)
for example:
USE DB;
GO
EXEC sp_rename 'Table.Name', 'NY_Name', 'COLUMN';
GO

One way to get it would be to use dynamic SQL, but try to avoid doing that if you can help it.
Here's one way:
/* --create table to test
CREATE TABLE dbo.WTF (
Name VARCHAR(10),
Birthday VARCHAR(10),
Year VARCHAR(10),
Size VARCHAR(10)
)
*/
DECLARE #prefix VARCHAR(10) = 'NY_'
DECLARE #sql NVARCHAR(1000) = N'';
DECLARE #columns VARCHAR(1000) = '';
SELECT #columns = #columns + c.name + ' ' + QUOTENAME(#prefix + c.name) + ',
'
FROM sys.tables t
INNER JOIN sys.columns c
ON t.object_id = c.object_id
WHERE t.name = 'WTF'
ORDER BY c.column_id
set #columns = left(#columns, len(#columns) - 3) --remove last comma and cr lf
set #sql = N'SELECT
' + #columns + '
FROM dbo.WTF'
select #sql
exec sp_executesql #sql
This returns:
SELECT
Name [NY_Name],
Birthday [NY_Birthday],
Year [NY_Year],
Size [NY_Size]
FROM dbo.WTF
NY_Name NY_Birthday NY_Year NY_Size
---------- ----------- ---------- ----------
Good luck!

Related

Dynamic query to find the length of rows in a column in sql server

I need to prepare a dynamic query to find the length of all the rows in a column in sql server. let say if there are 10 columns for a table with 100 rows. I need to find the row length for each column dynamically.
Assuming that your all columns are string columns, though len function should work anyways.
-- replace 'mytable' with the actual table name
declare #tableName nvarchar(128) = 'mytable';
declare #queryToRun nvarchar(max) = '';
-- IMPORTANT: following query is putting each column name as len_columnName
select #queryToRun = #queryToRun + ', len([' + c.name + ']) as [len_' + c.name + ']
'
from sys.tables as t
inner join sys.columns as c on t.object_id = c.object_id
where t.name = #tableName
-- removing the first comma
set #queryToRun = SUBSTRING(#queryToRun, 2, len(#queryToRun) - 1);
-- creating the query with dynamic column names
set #queryToRun = 'select ' + #queryToRun + ' from ' + #tableName;
--print #queryToRun
exec (#queryToRun)
you can use sys.tables and sys.all_columns
declare #Sql nvarchar(max)='select '
select #Sql=#sql+'Sum(len('+QUOTENAME(c.name)+')) as Len'+QUOTENAME(c.name)+',' from sys.tables t join sys.all_columns c on t.object_id=c.object_id
where t.Name='YourTableName'
set #Sql = left(#Sql,len(#sql)-1)+' from YourTableName'
select #Sql
Try this Script you will get data length of each columns in table dynamically
IF OBJECT_ID('dbo.LenghtOfRows')IS NOT NULL
DROP TABLE LenghtOfRows
CREATE TABLE LenghtOfRows (
Id Int IDENTITY,
Sqlode nvarchar(max)
)
DECLARE #SQL NVARCHAR(max),
#MinId INT,
#MaxId INT,
#tableName Varchar(100) ='StudentLabExamScore', --Give Table name here
#GetSQL NVARCHAR(max)
SET #SQL = 'SELECT ''SELECT DATALENGTH(''+COLUMN_NAME+'') As Len_'' +COLUMN_NAME +'' FROM ''+TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = '''+#tableName+''''
PRINT #SQL
INSERT INTO LenghtOfRows(Sqlode)
EXEC ( #SQL)
SELECT #MinId = MIN(Id) from LenghtOfRows
SELECT #MaxId = MAX(Id) from LenghtOfRows
WHILE (#MInId <=#MaxId)
BEGIN
SELECT #GetSQL= Sqlode FROM LenghtOfRows WHERE id=#MInId
EXEC (#GetSQL)
PRINT #GetSQL
SET #MInId=#MInId+1
END

i want to fetch data according to tables which are dynamic means their name might change in databse from time to time

I am working on a query, where I need to fetch data from tables which are dynamic in nature, meaning their name might change in the database from time to time.
So, first step is that from the schema, I will get to know what the recent table names are under that schema from which I have to fetch the data, but the second part is the difficult one for me: Once I've got the table name, how could I use those tables to fetch data inside them?
You can use dynamic SQL for that
use tempdb
GO
CREATE TABLE dynamic_table
(
a INT,
b INT);
GO
INSERT INTO dynamic_table VALUES (1,1);
GO
DECLARE #table_name VARCHAR(200) = 'dynamic_table';
DECLARE #sql VARCHAR(MAX),
#columns VARCHAR(MAX);
SELECT #columns =
d FROM (
SELECT DISTINCT SUBSTRING(
(
SELECT ',' + ds1.name AS [text()]
FROM sys.columns ds1
WHERE ds1.object_id = ds2.object_id
ORDER BY ds1.name FOR XML PATH('')
), 2, 1000) AS d
FROM sys.columns ds2 WHERE ds2.object_id = OBJECT_ID(#table_name)
) a;
SET #sql = 'SELECT ' + #columns + ' FROM ' + #table_name;
EXEC (#sql)
DROP TABLE dynamic_table
GO
Use the below one and change as per your requirement, Hope it's helpful.
Declare #Table varchar(100)
Declare #Sql nvarchar(max)
Set #Table = 'etl_run'
Set #Sql = 'Select * from ' + #Table
exec (#Sql)

Select columns name from subquery in main query

I have a question about select in SQL Server.
First I'm getting columns name from temp table with proper type query looks like this:
select
sc.name, st.name
from
tempdb.sys.columns sc
left join
sys.types st on sc.system_type_id = st.system_type_id
where
object_id = object_id('tempdb..#_tmpDocs')
and st.name in ('char', 'varchar', 'nvarchar')
Result is a list of columns with type I want, but next I want to select those columns in different query so if ill save result from above query into temp table with name #columns with it be possible to do something like
select (select * from #columns) from target_table
Here's a dynamic sql that will do what you need:
CREATE TABLE #_tmpDocs (id INT, x CHAR(10), y VARCHAR(100))
DECLARE #cols NVARCHAR(1000)
DECLARE #sql NVARCHAR(1000)
SELECT #cols = COALESCE(#cols + ',', '') + QUOTENAME(SC.name)
FROM tempdb.sys.columns sc
LEFT JOIN sys.types st ON sc.system_type_id = st.system_type_id
WHERE object_id = OBJECT_ID('tempdb..#_tmpDocs')
AND st.name IN ( 'char', 'varchar', 'nvarchar' )
SET #sql = 'select ' + #cols + ' from #_tmpDocs'
PRINT #sql
EXEC (#sql)
EXEC sp_executesql #sql
Chose between EXEC (#sql) and EXEC sp_executesql #sql based on you needs - see here to get an idea of what each is doing.
I don't think you can reference columns dynamically in SQL like that. Just doing a pure sql version, it won't work:
declare #x varchar(50) = 'MyColumn';
select #x from dbo.MyTable
You'll need to use dynamic sql, and build a string:
declare #x nvarchar(50) = 'MyColumn';
declare #y nvarchar(250) = 'select ' + #x + ' from dbo.MyTable';
EXECUTE sp_executesql #y
So in your case you may want to loop through your return result or otherwise turn it into a string of column names that can be concatenated to a larger query (like above).
Did you try this?
SELECT *
FROM tempdb.sys.columns
WHERE object_id = object_id('tempdb..#columns');

SQL Server : query to insert data into table from another table with different struct

I have two tables in two different databases.
My first table is an older version and has fewer columns than the second table.
I want to copy the contents of my old table to my new table.
In each database table there are several distribution in this case.
How can I do to quickly copy data from old tables to the new without having to write the column names manually for each table?
Thanks!
You can "avoid writing the column names manually" in SSMS by dragging and dropping the "Columns" folder under the table in the Object Explorer over to a query window (just hold the dragged item over whitespace or the character position where you want the names to appear). All the column names will be displayed separated by commas.
You could also try something like this to get just the list of columns that are common between two tables (then writing the INSERT statement is trivial).
SELECT
Substring((
SELECT
', ' + S.COLUMN_NAME
FROM
INFORMATION_SCHEMA.COLUMNS S
INNER JOIN INFORMATION_SCHEMA.COLUMNS D
ON S.COLUMN_NAME = D.COLUMN_NAME
WHERE
S.TABLE_SCHEMA = 'dbo'
AND S.TABLE_NAME = 'Source Table'
AND D.TABLE_SCHEMA = 'dbo'
AND D.TABLE_NAME = 'Destination Table'
FOR XML PATH(''), TYPE
).value('.[1]', 'nvarchar(max)'), 3, 21474783647)
;
You could also create an SSIS package that simply moves all the data from one table to the other. Column names that match would automatically be linked up. Depending on your familiarity with SSIS, this could take you 2 minutes, or it could take you 2 hours.
The following code should do the work.
Basically what it does is:
1. Collects column names from both tables.
2. Intersects the column names in order to filter out columns that exists only in 1 table.
3. Get a string which is the column names delimited by a comma.
4. Using the string from stage #3 creating the insert command.
5. Executing the command from stage #4.
--BEGIN TRAN
DECLARE #oldName NVARCHAR(50) = 'OldTableName', #newName NVARCHAR(50) = 'newTableName'
DECLARE #oldDBName NVARCHAR(50) = '[OldDBName].[dbo].['+#oldName+']', #newDBName NVARCHAR(50) = '[newDBName].[dbo].['+#newName+']'
/*This table variable will have columns that exists in both table*/
DECLARE #tCommonColumns TABLE(
ColumnsName NVARCHAR(max) NOT NULL
);
INSERT INTO #tCommonColumns
SELECT column_name --,*
FROM information_schema.columns
WHERE table_name = #oldName
AND COLUMNPROPERTY(object_id(#oldName), column_name, 'IsIdentity') = 0 --this will make sure you ommit IDentity columns
INTERSECT
SELECT column_name --, *
FROM information_schema.columns
WHERE table_name = #newName
AND COLUMNPROPERTY(object_id(#newName), column_name,'IsIdentity') = 0--this will make sure you ommit IDentity columns
--SELECT * FROM #tCommonColumns
/*Get the columns as a comma seperated string */
DECLARE #columns NVARCHAR(max)
SELECT DISTINCT
#columns = STUFF((SELECT ', ' + cols.ColumnsName
FROM #tCommonColumns cols
FOR XML Path('')),1,1,'')
FROM #tCommonColumns
PRINT #columns
/*Create tyhe insert command*/
DECLARE #InserCmd NVARCHAR(max)
SET #InserCmd =
'INSERT INTO '+#newDBName +' ('+#columns +')
SELECT '+#columns +' FROM '+#oldDBName
PRINT #InserCmd
/*Execute the command*/
EXECUTE sp_executesql #InserCmd
--ROLLBACK
Please note that this script might fail if you have FOREIGN KEY Constraints That are fulfiled in the old table but not in the new table.
Edit:
The query was updated to omit Identity columns.
Edit 2:
query updated for supporting different databases for the tables (make sure you set the #oldName ,#newName, #oldDBName, #newDBName variables to match actual credentials).
Thanks all !
I propose that it's more generic :)
--BEGIN TRAN
DECLARE #Tablename NVARCHAR(50)
SET #Tablename = 'tableName'
DECLARE #Schemaname NVARCHAR(50)
SET #Schemaname = 'schemaName'
DECLARE #Datasource NVARCHAR(50)
SET #Datasource = 'dataSource'
DECLARE #Datadest NVARCHAR(50)
SET #Datadest = 'dataDestination'
/*This table variable will have columns that exists in both table*/
DECLARE #tCommonColumns TABLE(
ColumnsName NVARCHAR(max) NOT NULL
);
--INSERT INTO #tCommonColumns
DECLARE #sql NVARCHAR(max)
SET #sql = 'SELECT column_name
FROM ' + #Datasource + '.information_schema.columns
WHERE table_name = ''' + #Tablename + '''
AND COLUMNPROPERTY(object_id(''' + #Datasource + '.' + #Schemaname + '.' + #Tablename + '''), column_name, ''IsIdentity'') = 0' --this will make sure you ommit IDentity columns
SET #sql = #sql + ' INTERSECT
SELECT column_name
FROM ' + #Datadest + '.information_schema.columns
WHERE table_name = ''' + #Tablename + '''
AND COLUMNPROPERTY(object_id(''' + #Datadest + '.' + #Schemaname + '.' + #Tablename + '''), column_name, ''IsIdentity'') = 0' --this will make sure you ommit IDentity columns'
INSERT INTO #tCommonColumns EXECUTE sp_executesql #sql
-- SELECT * FROM #tCommonColumns
/*Get the columns as a comma seperated string */
DECLARE #columns NVARCHAR(max)
SELECT DISTINCT
#columns = STUFF((SELECT ', ' + cols.ColumnsName
FROM #tCommonColumns cols
FOR XML Path('')),1,1,'')
FROM #tCommonColumns
--PRINT #columns
/*Create tyhe insert command*/
DECLARE #InserCmd NVARCHAR(max)
SET #InserCmd =
'INSERT INTO '+#Datadest+'.'+#Schemaname+'.'+#Tablename +' ('+#columns +')
SELECT '+#columns +' FROM '+#Datasource+'.'+#Schemaname+'.'+#Tablename
PRINT #InserCmd
/*Execute the command*/
--EXECUTE sp_executesql #InserCmd
--ROLLBACK
Something like this:
Insert into dbo.Newtbl
SELECT * FROM dbo.OldTbl

Dynamic SQL - Picking the values from the temp table

I have a temp table that has the following information.
TableName ColumnName PrimaryKeyColumnName Primarykey(A GUID)
(4 columns)
I need to include one more new column Value that should grab data based on the condition below
"for each row in the temp table"
select ColumnName from TableName where PrimaryKeyColumnName = Primarykey
To be even more precise , the query must retrieve the values from the table directly.
I am sure this can be achieved using cursor. But it might impact my query performance.
Could this be achieved using sp_sqlexecute? I tried converting the query as a varchar.
Like this
set #sql = 'select '+ #final.[primary field] +'from ' + #final.tablename +
'where '+ #final.PrimaryKeyColumnName + '='+ #final.Primarykey
exec sp_sqlexecute #sql
Possible this be helpful for you -
IF OBJECT_ID('tempdb.dbo.#temp') IS NOT NULL
DROP TABLE #temp
GO
CREATE TABLE #temp
(
[primary field] SYSNAME,
tablename SYSNAME,
PrimaryKeyColumnName SYSNAME,
Primarykey SYSNAME
)
INSERT INTO #temp ([primary field], tablename, PrimaryKeyColumnName, Primarykey)
VALUES
('[column1]','[table1]','[column3]', '[column12]'),
('[column2]','[table2]','[column4]', '[column24]')
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = (
SELECT CHAR(13) + 'SELECT '+ [primary field] + ' FROM ' + tablename +
' WHERE '+ PrimaryKeyColumnName + ' = '+ Primarykey
FROM #temp
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
PRINT #SQL
--EXEC sys.sp_executesql #SQL
Output -
SELECT [column1] FROM [table1] WHERE [column3] = [column12]
SELECT [column2] FROM [table2] WHERE [column4] = [column24]
I am not sure that I understood what you are trying to do but try this:
declare #sql varchar(8000);
set #sql = null;
select #sql =
coalesce(#sql+' union all select '+ColumnName+' from '+ tablename,
'select '+ColumnName+' from '+ tablename)
from final where ColumnName = PrimaryKeyColumnName;
exec sp_sqlexecute #sql;
Notice that the #sql is limited -in my sample 8000- if the temp table you have is too big you gonna have to make a separate executes,needs some changes in the code.
Always you have to set an initial value for #SQL as null.
I think no need for cursor, this will be solved using some SQL tricks.
Hope this will help...
Create Table #tempValueFetch
(
TableName sysname,
PrimaryKeyColumnName sysname,
AttributeColumnName sysname,
Primaryfield sysname,
PrimaryKey sysname,
Label nvarchar(max),
Value nvarchar(max)
)
this temp table has been populated with 5 columns namely TableName,PrimaryKeyColumnName,AttributeColumnName ,Primaryfield ,PrimaryKey
The columns label and value has to updated dynamically.Note that primary key is a uniqueidentifier