I have a table where I am storing all tables name and column name, now I want to get data according to that table with different conditions.
I will use one single query column name and table name will take dynamically from this table and than I will use in select query and will get data from respective column and table.
Table name is ADE_ColumnIndexing
In this table I have all table names as TableName column, and column names as name column...
Now I want to use
select fieldname
from tablename
where Id = newdata
This query will return data of that column and table... I mean tablename = ade_log and columnname = history...
So my query will be select history from ade_log... Is it possible?
It's possible to build and execute dynamic sql, though it doesn't seem like a good aproach:
DECLARE #Sql varchar(max)
SELECT #Sql = 'SELECT '+ ColumnName +
' FROM '+ TableName +
' WHERE Id = '+ IdValue
FROM ADE_ColumnIndexing
WHERE TableName = #TableName
AND ColumnName = #ColumnName
EXEC(#Sql)
I think if you use the ID column for search, definitely not recommended as it may seem to me, the IDVal is auto-increment (correct me if i'm wrong). So why not use
exec('select [' + #column_name + '] from [' + #tablename + ']');
if you want an added validation if the table or column exists, you may query in sys.
if (
select
COUNT(*)
from sys.tables tb
left join sys.columns c
on
tb.object_id = c.object_id
where
tb.name = #tablename
and c.name = #columnname
) != 0
begin
exec('select [' + #column_name + '] from [' + #tablename + ']');
end
else
begin
select 'table or column does not exist'
end
EDIT : Seems like your table has "queries" as a row, then see my simple script below if I understand you correctly....(hopefully)
CREATE TABLE test (qry nvarchar(4000)) -- test query table
CREATE TABLE test1 (sales decimal(18,2)) -- sales table
INSERT INTO test1 (sales) -- dummy records for sales table
values (5923.59), (5923.52),(5923.51)
INSERT INTO test (qry) -- dummy records for query table
values ('select * from test1 where sales = 5923.59')
,('select * from test1 where sales = 5923.52')
,('select * from test1 where sales = 5923.51')
declare #myqry nvarchar(4000) = (SELECT qry + '; ' AS [text()] FROM test FOR XML PATH('')) -- from records to 1 query statement with multiple table results
declare #myqry2 nvarchar(4000) = SUBSTRING(
(SELECT qry + ' union all ' AS [text()] FROM test FOR XML PATH(''))
,0
,LEN((SELECT qry + ' union all ' AS [text()] FROM test FOR XML PATH(''))) - 9
)
-- from records to 1 query statement with single table results
select 'my query', #myqry -- see content of #myqry
select 'my query 2', #myqry2 -- see content of #myqry2
EXEC(#myqry) -- execute #myqry
EXEC(#myqry2) -- execute #myqry2
EDIT : This is my last attempt for your case. Please try this sample code set which still uses table:[test] and table:[test1]
DECLARE #intloop INT = 1 -- variable setter for number of loops
,#qry nvarchar(4000) = '' -- variable setter for the looping query
SELECT ROW_NUMBER() OVER (ORDER BY qry) AS id, qry INTO #tmpQueries FROM [test] -- create temp table for fake 'id'
CREATE TABLE #tmpQuery (id int, qry nvarchar(4000), res nvarchar(4000)) -- table result container
CREATE TABLE #tmpInsert (res nvarchar(4000)) -- execute query container
WHILE (#intloop < (SELECT COUNT(*) FROM #tmpQueries) + 1)
BEGIN
SET #qry = (SELECT TOP 1 qry FROM #tmpQueries WHERE id = #intloop) -- get the qry base from ID
DELETE FROM #tmpInsert -- delete records of query container
INSERT INTO #tmpInsert -- insert records into query container
EXEC (#qry) -- execute qry
INSERT INTO #tmpQuery (id, qry, res)
VALUES (#intloop, #qry, (SELECT TOP 1 res FROM #tmpInsert)) -- transfer id, qry and result into #tmpQuery table
SET #intloop = #intloop + 1 -- increment record
END
SELECT * FROM #tmpQuery -- select all records in #tmpQuery table
DROP TABLE #tmpQueries
DROP TABLE #tmpQuery
DROP TABLE #tmpInsert
NEW TABLE SAMPLE STRUCT : Create identity ID's for test and test1, and specify ID inside query. (notice the select * from test1 before into select id, sales from test1)
CREATE TABLE test (id int identity(1,1), qry nvarchar(4000)) -- test query table
CREATE TABLE test1 (id int identity(1,1), sales decimal(18,2)) -- sales table
INSERT INTO test1 (sales) -- dummy records for sales table
values (5923.59), (5923.52),(5923.51)
INSERT INTO test (qry) -- dummy records for query table
values
('select id, sales from test1 where sales = 5923.59')
,('select id, sales from test1 where sales = 5923.52')
,('select id, sales from test1 where sales = 5923.51')
SIMPLIFIED SCRIPT : Assuming all ID's of test and test1 are siblings, you can simply do the query this way.
declare #myqry2 nvarchar(4000) = SUBSTRING(
(SELECT qry + ' union all ' AS [text()] FROM test FOR XML PATH(''))
,0
,LEN((SELECT qry + ' union all ' AS [text()] FROM test FOR XML PATH(''))) - 9
)
CREATE TABLE #tmpResult(id int, qry nvarchar(4000))
INSERT INTO #tmpResult
EXEC(#myqry2) -- execute #myqry2
SELECT
tr.id
, t.qry
, tr.qry AS [sales]
FROM [test] t
LEFT JOIN #tmpResult tr
ON
t.id = tr.id
DROP TABLE #tmpResult
EDIT : We can remove the substring, but as per your request, all rows must be in single table result, so "union all" can't be un-done, unless you have your own ways, that's a plus.
select
*,
case
when id = 1 then ' union all '
when id = 2 then ' union all '
else ''
end as [row_extender]
into #tmptest
from test
--drop table #tmptest
declare #myqry2 nvarchar(4000) = (SELECT qry + row_extender AS [text()] FROM #tmptest FOR XML PATH(''))
CREATE TABLE #tmpResult(id int, qry nvarchar(4000))
INSERT INTO #tmpResult
EXEC(#myqry2) -- execute #myqry2
SELECT
tr.id
, t.qry
, tr.qry AS [sales]
FROM [test] t
LEFT JOIN #tmpResult tr
ON
t.id = tr.id
DROP TABLE #tmpResult
DROP TABLE #tmptest
Related
create table T1
(
Name varchar(50),
Address varchar(50),
Tel varchar(50)
);
create table T2
(
ParamName varchar(50),
ParamValue Varchar(60),
TableName varchar(50)
);
insert into T2 values('Name', 'test', 'Member');
insert into T2 values('Address', 'testAdd', 'Member');
insert into T2 values('Tel', 'test', 'Member');
insert into T1(Select distinct ParamName from T2)
values(select ParamValue from T2 )
I'm looking for a way to do a insertion to T1 table by getting value and column name from T2 table.need to get column name from T2 table and Value to that particular column
You can use this:
INSERT INTO T2(Column1,Column2)
SELECT Column1, Column2 FROM T1
GROUP BY Column1;
You could try using a pivot query on T2 to get the names, addresses, and telephone numbers onto a single row for each table name. Then, just do an INSERT INTO ... SELECT as you were, except use the pivoted result.
INSERT INTO T1 (Name, Address, Tel)
SELECT
MAX(CASE WHEN ParamName = 'Name' THEN ParamValue END) AS Name,
MAX(CASE WHEN ParamName = 'Address' THEN ParamValue END) AS Address,
MAX(CASE WHEN ParamName = 'Tel' THEN ParamValue END) AS Tel
FROM T2
GROUP BY TableName
-- WHERE TableName IN ('Member', ...)
You can uncomment the WHERE clause if you want to restrict the insert to certain table names.
As a general comment, if you are doing this to get your data into a more normalized form, then I think it is good. But if you plan on storing your data like this long term, you might want to reconsider your table design.
Your table structure doesn't make much sense. There is no obvious logical relation between the tables. Is the second one just a buffer table?
In any case however, if you want to insert values from a table into another table you do it like that:
INSERT INTO [target_table] ([target_column_1], [target_column_2], ..., [target_column_n])
SELECT [source_column_1], [source_column_2], ..., [source_column_n]
FROM [source_table]
WHERE [conditon]
I think you are looking like..
INSERT INTO T1(Name)
SELECT DISTINCT ParamName FROM T2
DECLARE #TableName varchar(50) = 'T1'
DECLARE #ColumnName varchar(MAX)
SELECT #ColumnName= coalesce(#ColumnName + ', ', '') + a.COLUMN_NAME
from (SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
inner join T2 on TableName = TABLE_NAME
WHERE TABLE_NAME = #TableName and ParamName = COLUMN_NAME) a;
print #ColumnName
declare #ParamName varchar(MAX)
SELECT #ParamName = coalesce(#ParamName + ', ', '') + ''''+a.ParamValue+''''
from (SELECT COLUMN_NAME,ParamValue
FROM INFORMATION_SCHEMA.COLUMNS
inner join T2 on TableName = TABLE_NAME
WHERE TABLE_NAME = #TableName and ParamName = COLUMN_NAME) a;
print #ParamName
declare #QUERY nvarchar(MAX);
SET #QUERY = 'INSERT INTO T1 ('+#ColumnName+')
VALUES ('+#ParamName+')'
EXEC sp_executesql #QUERY
this is the answer what i expect ,thanks all for your help
I have a stored procedure where I am running/executing a declared variable which is set to a select query for pivot table, important thing is that that pivot table is transforming column to n number of rows. Yes the rows are not fixed that is why I have problem in creating a temp table with fixed column. What I want is that create a temp table by executing the execute command so the columns would be determined by the select/insert statement.
Below is the query.
SELECT #cols = #cols + QUOTENAME(item) + ','
FROM (select distinct item from #TableData ) as tmp
select #cols = substring(#cols, 0, len(#cols))
set #tequery =
'SELECT * from
(
select Sno, item, SoldValue from #TableData
) mytbl
pivot
(
max(ValueInDhs) for GroupName in (' + #cols + ')
) newTable'
execute(#tablequery)
I want to store the result of #tequery into a temp table or better this stored procedure should return the result set instead of int as this procedure I have inserted into my entity framework where its showing(after insert) its return type as int.
You could do this with a global (##) temp table, although you'd have to be careful of multiple processes doing this at the same time. Here is an abitrary example:
declare #sql varchar(max) = '
select *
into ##temp -- create global temp table
from (
select name
, create_date = convert(varchar(4), create_date, 102)
from sys.objects) as o
pivot ( count(name) for create_date in ([2017],[2016],[2012], [2009],[2003])
) as p;
'
exec (#sql)
-- if you do not want to use the global table, select it into a temp table
select * into #temp from ##temp
-- and drop the global
drop table ##temp
select * from #temp
I am looking to return a view name and all record ID's where billingAddress != shippingAddress to further review. I need to query all views in one database. This is my thought process and if their is a better way or faster way to write the query by all means help me out!
What I am stuck on is how to return the view name with the recordID?
Create Table #T (ID Int Identity Not Null, ViewNames VARCHAR(1000)
Create Table #2 (viewNames varchar(1000))
Insert Into #T (ViewNames)
Select '['+C.Table_Catalog+'].['+C.Table_Schema+'].['+C.Table_Name+']' TableName
FROM Information_Schema.Columns c
Join information_schema.Tables T on C.Table_Catalog = T.Table_Catalog
AND C.Table_Schema = T.Table_Schema
AND C.Table_Name = T.Table_Name
Where T.Table_Type = 'View'
Group By '['+C.Table_Catalog+'].['+C.Table_Schema+'].['+C.Table_Name+']'
---Now this is the piece that I am stuck on as I do not know how to insert the view name into the table as well on each iteration
Declare #N int, #Str nvarchar(2000), #viewname nvarchar(2000), #MaxID int
Set #N = 1
Select #MaxID = Max(ID)
From #T
While (#N<#MaxID)
Begin
Select #viewname= viewname
From #T
Set #Str = ' Insert Into #2(viewname)
Select Top 1 '''+#viewname+'''
From '+#viewname+'
where exists(Select recordID from '+#viewname+' where [shipaddress] != [billaddress] ) '
Exec sp_eecutesql #str
Set #N = #N + 1
End
Select * from #t
Try changing your dynamic query like this.
You said you wanted the view name, and record id, so you need to add a column to #2
SET #Str = 'INSERT INTO #2(viewname, recordid)
SELECT ''' + quotename(#viewname) + ''', recordID
FROM '+ quotename(#viewname) + '
WHERE [shipaddress] != [billaddress]'
EXEC sp_executesql #str
Unless you're sure of the object names, you should try and use quotename when building up dynamic SQL
You do have a problem in your logic though...
You are missing a where clause in the query that assigns the value to #viewname
Try this...
SELECT #viewname= viewname
FROM #T
WHERE ID = #N
I do not understand sql returns set of rows so your variable #viewname can not be assigned value row by row. By default your #viewname will be assigned last row of table T.
My code:
SELECT * INTO #t FROM CTABLE WHERE CID = #cid --get data, put into a temp table
ALTER TABLE #t
DROP COLUMN CID -- remove primary key column CID
INSERT INTO CTABLE SELECT * FROM #t -- insert record to table
DROP TABLE #t -- drop temp table
The error is:
Msg 8101,
An explicit value for the identity column in table 'CTABLE' can only
be specified when a column list is used and IDENTITY_INSERT is ON.
And I did set
SET IDENTITY_INSERT CTABLE OFF
GO
DECLARE
#cid INT,
#o INT,
#t NVARCHAR(255),
#c NVARCHAR(MAX),
#sql NVARCHAR(MAX);
SELECT
#cid = 10,
#t = N'dbo.CTABLE',
#o = OBJECT_ID(#t);
SELECT #c = STRING_AGG(QUOTENAME(name), ',')
FROM sys.columns
WHERE [object_id] = #o
AND is_identity = 0;
SET #sql = 'SELECT ' + #c + ' INTO #t
FROM ' + #t + ' WHERE CID = #cid;
INSERT ' + #t + '('+ #c + ')
SELECT ' + #c + ' FROM #t;'
PRINT #sql;
-- exec sp_executeSQL #sql,
-- N'#cid int',
-- #cid = #cid;
However it seems much easier to just build the following SQL and avoid the #temp table altogether:
SET #sql = 'INSERT ' + #t + '(' + #c + ')
SELECT ' + #c + ' FROM ' + #t + '
WHERE CID = #cid;';
PRINT #sql;
-- exec sp_executeSQL #sql,
-- N'#cid int',
-- #cid = #cid;
Try this:
SELECT * INTO #t FROM CTABLE WHERE CID = #cid
ALTER TABLE #t
DROP COLUMN CID
INSERT CTABLE --Notice that INTO is removed here.
SELECT top(1) * FROM #t
DROP TABLE #t
Test Script(Tested in SQL 2005):
CREATE TABLE #TestIDNT
(
ID INT IDENTITY(1,1) PRIMARY KEY,
TITLE VARCHAR(20)
)
INSERT #TestIDNT
SELECT 'Cybenate'
Try specifying the columns:
INSERT INTO CTABLE
(col2, col3, col4)
SELECT col2, col3, col4
FROM #t
Seems like it might be thinking you are trying to insert into the PK field since you are not explicitly defining the columns to insert into. If Identity insert is off and you specify the non-pk columns then you shouldn't get that error.
Here's an example to dynamically build a list of columns - excluding the primary key columns - and execute the INSERT
declare #tablename nvarchar(100), #column nvarchar(100), #cid int, #sql nvarchar(max)
set #tablename = N'ctable'
set #cid = 1
set #sql = N''
declare example cursor for
select column_name
from information_schema.columns
where table_name = #tablename
and column_name not in (
select column_name
from information_schema.key_column_usage
where constraint_name in (select constraint_name from information_schema.table_constraints)
and table_name = #tablename
)
open example
fetch next from example into #column
while ##fetch_status = 0
begin
set #sql = #sql + N'[' + #column + N'],'
fetch next from example into #column
end
set #sql = substring(#sql, 1, len(#sql)-1)
close example
deallocate example
set #sql = N'insert into ' + #tablename + '(' + #sql + N') select top(1) ' + #sql + ' from #t'
--select #sql
exec sp_executesql #sql
If using SQL Server Management Studio and your problems you have too many fields to type them all out except the identity column, then right click on the table and click "Script table as" / "Select To" / "New Query Window".
This will provide a list of fields that you can copy & paste into your own query and then just remove the identity column.
Try invoking the INSERT statement with EXEC:
SELECT * INTO #t FROM CTABLE WHERE CID = #cid
ALTER TABLE #t
DROP COLUMN CID
EXEC('INSERT INTO CTABLE SELECT top(1) * FROM #t')
DROP TABLE #t
You can't do this:
INSERT INTO CTABLE SELECT top(1) * FROM #t
Because the column listings aren't the same. You've dropped the PK column from #t, so you have 1 less column in #t than in CTABLE. This is the equivalent of the following:
INSERT INTO CTABLE(pk, col1, col2, col3, ...)
select top(1) col1, col2, col3, ...
from #t
This wouldn't work for obvious reasons. Similarly, you aren't going to be able to specify the * wildcard to do the insert if you're not inserting all of the columns. The only way to do the insert without including the PK is to specify every column. You can generate a list of columns through dynamic sql, but you'll have to specify them one way or another.
Is there a way to select the row from a temp table (table has only one row anyway), into another table that has some columns with differenet names? For example:
TempTable
FirstName LastName Column1 Column2
------------ ------------ ----------- -----------
Joe Smith OKC TX
OtherTable
FirstName LastName Region1 Region2 Region3
------------ ------------ ----------- ----------- ----------
NULL NULL NULL NULL NULL
I need to copy the data, in the same order as the columns from TempTable into OtherTable. TempTable will not always be the same....as in sometimes it will have 3 columns, sometimes just 2...etc. If it does not have the same number of columns as OtherTable, the the remaining "Region" columns should stay null.
The end result should be:
OtherTable
FirstName LastName Region1 Region2 Region3
------------ ------------ ----------- ----------- ----------
Joe Smith OKC TX NULL
PLUS the column names in TEMPTable will NEVER be the same...as in one time it will be "Column1"...the next time it could be "XXXXX1". That's why I just want to copy data only...the data will always be in the correct order...
LOL...does this even make sense? This is for SQL Server 2005
EDIT ........ Dynamic SQL Generation added
This code will generate INSERT statements to INSERT from #TEMP into #TEMP. You can tweak it to suit your purpose if you are going from #temp to regular tables.
SET NOCOUNT ON
DROP Table #TempTable1
DROP Table #TempTable2
GO
DROP Function GenerateInserts
GO
Create Function GenerateInserts
(
#SourceTable VarChar (100),
#DestinationTable VarChar (100)
)
Returns VarChar (MAX)
AS
BEGIN
DECLARE #SelectString VarChar (MAX)
DECLARE #InsertString VarChar (MAX)
DECLARE #SQLString VarChar (MAX)
DECLARE #SourceColumnCount INTEGER
DECLARE #DestinationColumnCount INTEGER
DECLARE #ColumnCount INTEGER
DECLARE #Counter INTEGER
SELECT #SourceColumnCount = COUNT (*)
FROM tempdb..syscolumns
WHERE id=object_id(#SourceTable)
SELECT #DestinationColumnCount = COUNT (*)
FROM tempdb..syscolumns
WHERE id=object_id(#DestinationTable)
SET #ColumnCount = #SourceColumnCount
IF #DestinationColumnCount < #ColumnCount
SET #ColumnCount = #DestinationColumnCount
SET #Counter = 0
SET #SelectString = ' INSERT INTO ' + #DestinationTable + ' '
SET #InsertString = ' INSERT INTO ' + #DestinationTable + ' '
SET #SelectString = ''
SET #InsertString = ''
WHILE #Counter <= #ColumnCount
BEGIN
SELECT #SelectString = #SelectString + ', ' + Name
FROM TempDB..SysColumns
WHERE Id = Object_Id (#SourceTable)
AND ColOrder = #Counter
SELECT #InsertString = #InsertString + ', ' + Name
FROM TempDB..SysColumns
WHERE Id = Object_Id (#DestinationTable)
AND ColOrder = #Counter
SET #Counter = #Counter + 1
END
SET #InsertString = 'INSERT INTO ' + #DestinationTable + ' (' + STUFF ( #InsertString, 1, 2, '') + ') '
SET #SelectString = 'SELECT ' + STUFF ( #SelectString, 1, 2, '') + ' FROM ' + #SourceTable
SET #SQLString = #InsertString + '
'+ #SelectString
RETURN #SQLString
END
GO
Create Table #TempTable1
(
Col1 VarChar (10),
Col2 VarChar (10),
Col3 VarChar (10),
Col4 VarChar (10),
Col5 VarChar (10)
)
Create Table #TempTable2
(
MyCol1 VarChar (10),
MyCol2 VarChar (10),
MyCol3 VarChar (10),
MyCol4 VarChar (10),
MyCol5 VarChar (10),
MyCol6 VarChar (10)
)
SELECT dbo.GenerateInserts ('tempdb..#TempTable1', 'tempdb..#TempTable2')
OLD ANSWER
Yes you can do this but you have to write different statements for each type of INSERT. You do have to specify column names in both places - the INSERT INTO and the SELECT
If you have the same number of columns in your Source and Destination tables, do this
INSERT INTO Table1 (Column1, Column2, Column3)
SELECT MyColumn01, MyColumn02, MyColumn03
FROM MyTable
What this will do is map as follows:
MyTable.MyColumn01 -> Table1.Column1
MyTable.MyColumn02 -> Table1.Column2
MyTable.MyColumn03 -> Table1.Column3
If the Source has less columns, you can use a NULL value in place of the column name
INSERT INTO Table1 (Column1, Column2, Column3)
SELECT MyColumn01, MyColumn02, NULL AS MyColumn03
FROM MyTable
OR you can just use two column names
INSERT INTO Table1 (Column1, Column2)
SELECT MyColumn01, MyColumn02
FROM MyTable
If the destination table has less columns than the source, then you have to ignore columns from the source
INSERT INTO Table1 (Column1, Column2, Column3)
SELECT MyColumn01, MyColumn02, NULL AS MyColumn03 /* MyColumn04, MyColumn05 are ignored */
FROM MyTable
You could do something with dynamic SQL.
I recommend reading "The Curse and Blessings of Dynamic SQL -
Dealing with Dynamic Table and Column Names" if this is new to you.
Example follows. You could improve this to be sure that source and destination columns are of compatible types or to exclude identity or computed columns for example but it should give you an idea.
DECLARE #SourceTable sysname
DECLARE #DestTable sysname
SET #SourceTable = '[dbo].[#TempTable]'
SET #DestTable = '[dbo].[OtherTable]'
DECLARE #DynSQL1 NVARCHAR(MAX)
DECLARE #DynSQL2 NVARCHAR(MAX)
SELECT
#DynSQL1 = ISNULL(#DynSQL1 + ',','') + QUOTENAME(sc1.name),
#DynSQL2 = ISNULL(#DynSQL2 + ',','') + QUOTENAME(sc2.name)
FROM tempdb..syscolumns sc1
JOIN syscolumns sc2
ON sc1.colorder = sc2.colorder /*Match up the columns by column order*/
WHERE sc1.id=OBJECT_ID('tempdb.' + #SourceTable) AND sc2.id=OBJECT_ID(#DestTable)
IF ##ROWCOUNT = 0
RETURN
SET #DynSQL1 = 'INSERT INTO ' + #DestTable + ' (' + #DynSQL2 + ')
SELECT ' + #DynSQL1 + ' FROM '+ #SourceTable +';'
EXEC sp_executesql #DynSQL1
You can specify the columns of the target table:
INSERT INTO OtherTable (FirstName, LastName, Region1, Region2)
SELECT FirstName, LastName, Column1, Column2 FROM TempTable;
In this example, OtherTable.Region3 will end up NULL (or if it has a DEFAULT value, it'll use that).
The count of columns in the INSERT must match the count of columns in the SELECT. So you must know how many columns in TempTable and make the list of columns for the insert match.
But there's no way to do it with implicit columns, if you're just throwing SELECT * around.
Re your comment: You can use the INFORMATION_SCHEMA to query the count and the names of the columns in the table.
SELECT COLUMN_NAME
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_CATALOG = 'tempdb' AND TABLE_SCHEMA = 'MySchema'
AND TABLE_NAME LIKE 'MyTempTable%';
Then you would write application code to create your SQL INSERT...SELECT statement based on the results from this information_schema query.
Note: Querying temp tables through the information_schema requires special handling.