SELECTing the column names for another SELECT - possible? - mysql

I have a table t1 with a 'foo' column, and records containing 'bar' and 'baz' in column 'foo'. I also have a table t2 with columns 'bar', 'baz' and 'quux'. I want to do something like the following:
SELECT (SELECT foo from t1) FROM t2;
that is, get the two column names from t1 and query those columns of t2. If I try to do this with MonetDB, I get an error message:
cardinality violation (2>1)
so,
is there some other way to do this with MonetDB?
is this possible in MySQL? other DBMSes?
Example queries (or non-query directives followed by a query) are welcome.

first you need to select the columns into a variable and then use that variable to get tables
something like the following (it is not the actual implementation)
declare #colname varchar(250)
select #colname=foo from t1
select #colname from t2
this may be help.

This is how you can accomplish it in SQL Server
-- Create #T1 which contains names of columns and #T2 which contains the actual columns
CREATE TABLE #T1(colname nvarchar(max))
INSERT INTO #T1 (colname) VALUES ('b')
INSERT INTO #T1 (colname) VALUES ('c')
CREATE TABLE #T2(a int IDENTITY(1,1), b DATETIME DEFAULT GETDATE(), c NVARCHAR(max) DEFAULT 'blah')
INSERT INTO #T2 DEFAULT VALUES
INSERT INTO #T2 DEFAULT VALUES
INSERT INTO #T2 DEFAULT VALUES
--#dSQL will contain the actual SQL string to be executed
DECLARE #dSQL nvarchar(max) = ' '
SELECT #dsql = CONCAT(#dsql,'[',colname,'],') FROM #T1
SELECT #dsql = CONCAT('SELECT',LEFT(#dsql,LEN(#dsql)-1),' FROM #T2')
--You can see the SQL query being executed
PRINT #dsql
--Actually execute it
exec sp_executesql #dsql

MS Sql dynamic sql example.
create table t1(foo varchar(100))
insert t1(foo)
values('bar,baz');
create table t2(bar int, baz int)
insert t2 (bar, baz)
values
(1,100),
(3,300);
declare #cmd varchar(max);
select #cmd= 'select '+ (select top(1) foo from t1) + ' from t2';
EXEC (#cmd);
Result
bar baz
1 1 100
2 3 300
Or may be foo contains column names in different rows, not exactly clear from your question.
create table t1(foo varchar(100))
insert t1(foo)
values('bar'),('baz');
create table t2(bar int, baz int)
insert t2 (bar, baz)
values
(1,100),
(3,300);
declare #cmd varchar(max);
select #cmd= 'select '+ stuff((select ','+ foo from t1 for xml path('')),1,1,'') + ' from t2';
EXEC (#cmd);

Related

How to set data to a variable from temporary table?

I have declared a temporary table
DECLARE #Table Table
(
ID INT IDENTITY(1,1),
TableColumn VARCHAR(MAX)
)
DECLARE #Temp VARCHAR(MAX)
SET #Temp='SELECT * FROM '+'#Table'+''
SELECT #Temp
EXEC (#Temp)
I want to set all data of #Table to a variable #Temp. The above I tried practice is correct? Presently it shows some error.
Msg 1087, Level 15, State 2, Line 1
Must declare the table variable "#Table".
I tried in the above methode then it shows error like
Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'AS'.
Msg 1087, Level 15, State 2, Line 9
Must declare the table variable "#Table". Msg 139, Level 15, State 1,
Line 0
Cannot assign a default value to a local variable.
Msg 137, Level 15, State 2, Line 17
Must declare the scalar variable "#Temp".
This is to show the difference between a table variable and a temp table. You can't do what you are trying to do. Also, #temp is just a variable to contain the SQL you want to execute. If you want the results in another variable, another will have to be declared.
DECLARE #Table TABLE (
ID INT IDENTITY(1, 1)
,TableColumn VARCHAR(MAX)
)
INSERT INTO #Table (TableColumn)
VALUES ('testing 1,2,3')
SELECT *
FROM #table --with table variables, you can only select in the scope
DECLARE #Temp VARCHAR(MAX)
SET #Temp = 'SELECT * FROM #Table'
BEGIN TRY
--SELECT #Temp
EXEC (#Temp) --fails, because #table is not in scope
END TRY
BEGIN CATCH
SELECT 'Table variable dynamic execution failed'
END CATCH
GO
CREATE TABLE #table (
ID INT IDENTITY(1, 1)
,TableColumn VARCHAR(MAX)
)
INSERT INTO #Table (TableColumn)
VALUES ('testing 1,2,3')
DECLARE #Temp VARCHAR(MAX)
SET #Temp = 'SELECT * FROM #Table' --you can select out of a temp table with dynamic sql, because it will remain in scope for called procedures
--SELECT #Temp
EXEC (#Temp)
DROP TABLE #table
EXEC() creates new context, variables are not visible there so you need to pass them as argument. But temp table and normal tables are visible. This is why you get
Must declare the table variable "#Table".
If you can change temp variables to temp tables.
SqlFiddleDemo
CREATE TABLE #Table
( ID INT IDENTITY(1,1),
TableColumn VARCHAR(MAX));
INSERT INTO #Table
VALUES ('aaa'), ('bbb');
DECLARE #Temp NVARCHAR(MAX) ='SELECT * FROM <placeholder>';
SET #Temp = REPLACE(#Temp, '<placeholder>', '#Table');
-- SELECT #Temp;
EXEC [dbo].[sp_executesql]
#Temp;
If you want to query temp variables you need to create table type and pass to dynamic sql as argument like:
Demo
CREATE TYPE MyTable AS TABLE
(
ID INT IDENTITY(1,1),
TableColumn VARCHAR(MAX)
);
DECLARE #Table AS MyTable;
INSERT INTO #Table
VALUES ('aaa'), ('bbb');
DECLARE #Temp NVARCHAR(MAX) ='SELECT * FROM '+'#Table'+'';
-- SELECT #Temp;
EXEC [dbo].[sp_executesql]
#Temp
,N'#Table MyTable READONLY'
,#Table;

GROUP CONCAT REPLACE sep strings

I am using the below statement to pull a unique value off a table from a field that is separated with "|". It looks like this: "40|180|408|360|40|1s66|80|59" My problem is that I can't seem to get this statement to allow me to pull a primary key field, id, and assign it to each unique item from the field string so I can actually use it later. Ideally, ID # 27 should be assigned to each of the values on this temp table from "40|180|408|360|40|1s66|80|59". Can anyone help with the below statement to allow me to insert and assign field id to this from table BlogImageBundle?
CREATE TEMPORARY TABLE test (postId INT(11), val CHAR(255));
SET #S1 = CONCAT("INSERT INTO test (val) VALUES ('",REPLACE((SELECT GROUP_CONCAT( DISTINCT `images`)
AS data FROM `BlogImageBundle`), "|", "'),('"),"');");
PREPARE stmt1 FROM #s1;
EXECUTE stmt1;
SELECT DISTINCT(val) FROM test;
This works but ONLY for one record. You will need to add another while loop that keeps track of the rowcount to deal with multiple records : http://sqlfiddle.com/#!6/d62f7/1
CREATE TABLE #Test
(
ID INT,
Initial VARCHAR(MAX)
)
CREATE TABLE #Test2
(
ID INT,
Final VARCHAR(MAX)
)
INSERT INTO #Test VALUES(27,'40|180|408|360|40|1s66|80|59')
DECLARE #String VARCHAR(MAX)
SET #string = (SELECT Initial FROM #Test)
DECLARE #StringInput VARCHAR(MAX)
SET #stringInput = (SELECT Initial FROM #Test)
WHILE LEN(#StringInput) > 0
BEGIN
SET #String = LEFT(#StringInput,ISNULL(NULLIF(CHARINDEX('|', #StringInput) - 1, -1),LEN(#StringInput)))
SET #StringInput = SUBSTRING(#StringInput,ISNULL(NULLIF(CHARINDEX('|', #StringInput), 0),LEN(#StringInput)) + 1, LEN(#StringInput))
INSERT INTO #Test2 (ID, Final)
SELECT ID,#string FROM #Test
END

How to copy data from one table to another "EXCEPT" one field

How to INSERT into another table except specific field
e.g
TABLE A
ID(auto_inc) CODE NAME
1 001 TEST1
2 002 TEST2
I want to insert CODE and NAME to another table, in this case TABLE B but except ID because it is auto increment
Note: I don't want to use "INSERT INTO TABLE B SELECT CODE, NAME FROM TABLE A", because I have an existing table with around 50 fields and I don't want to write it one by one
Thanks for any suggests and replies
This can't be done without specifying the columns (excludes the primary key).
This question might help you. Copy data into another table
You can get all the columns using information_schema.columns:
select group_concat(column_name separator ', ')
from information_schema.columns c
where table_name = 'tableA' and
column_name <> 'id';
This gives you the list. Then past the list into your code. You can also use a prepared statement for this, but a prepared statement might be overkill.
If this is a one time thing?
If yes, do the insert into tableA (select * from table B)
then Alter the table to drop the column that your dont need.
I tried to copy from a table to another one with one extra field.
source table is TERRITORY_t
* the principle is to create a temp table identical to the source table, adjust column fields of the temp table and copy the content of the temp table to the destination table.
This is what I did:
create a temp table called TERRITORY_temp
generate SQL by running export
CREATE TABLE IF NOT EXISTS TERRITORY_temp (
Territory_Id int(11) NOT NULL,
Territory_Name varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (Territory_Id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
copy over with
INSERT INTO TERRITORY_temp (Territory_Id, Territory_Name) VALUES
(1, 'SouthEast'),
(2, 'SouthWest'),
(3, 'NorthEast'),
(4, 'NorthWest'),
(5, 'Central');
or
INSERT INTO TERRITORY_temp
SELECT * from TERRITORY_t
add the extra field(s) to match with the new table
copy from the temp table to the destination table
INSERT INTO TERRITORY_new
SELECT * from TERRITORY_temp
Please provide feedback.
Step 1. Create stored procedure
CREATE PROCEDURE CopyDataTable
#SourceTable varchar(255),
#TargetTable varchar(255),
#SourceFilter nvarchar(max) = ''
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SourceColumns VARCHAR(MAX)=''
DECLARE #TargetColumns VARCHAR(MAX)=''
DECLARE #Query VARCHAR(MAX)=''
SELECT
#SourceColumns = ISNULL(#SourceColumns +',', '') + T.COLUMN_NAME
FROM
(
select name as COLUMN_NAME from sys.all_columns
where object_id = (select object_id from sys.tables where name = #SourceTable)
and is_identity = 0
)T
SELECT
#TargetColumns = ISNULL(#TargetColumns +',', '') + T.COLUMN_NAME
FROM
(
select name as COLUMN_NAME from sys.all_columns
where object_id = (select object_id from sys.tables where name = #TargetTable)
and is_identity = 0
)T
set #Query = 'INSERT INTO ' + #TargetTable + ' (' + SUBSTRING(#TargetColumns,2 , 9999) + ') SELECT ' + SUBSTRING(#SourceColumns,2 , 9999) + ' FROM ' + #SourceTable + ' ' + #SourceFilter;
PRINT #Query
--EXEC(#Query)
END
GO
Step 2. Run stored procedure
use YourDatabaseName
exec dbo.CopyDataTable 'SourceTable','TargetTable'
Explanations
a) dbo.CopyDataTable will transfer all data from SourceTable to TargetTable, except field with Identity
b) You can apply filter when call stored procedure, in order to transfer only row based on criteria
exec dbo.CopyDataTable 'SourceTable','TargetTable', 'WHERE FieldName=3'
exec dbo.CopyDataTable 'SourceTable','TargetTable', 'WHERE FieldName=''TextValue'''
c) Remove -- from --EXEC(#Query) WHEN finish

Getting summary of results from another stored procedure

I have one complex stored procedure that returns some rows with some calculated values
SELECT CalculatedField1 ,
CalculatedField2 ,
...
FROM ...
WHERE CONDITION
this sproc (lets call it procA) returns variable number of rows, depending on the WHERE condition. This works fine. What I need to do now is to write a stored procedure that will get the summary of these returned rows.
-- procB
SELECT SUM(CalculatedField1),
SELECT SUM(CalculatedField2),
...
FROM (EXEC procA params)
Is this possible?
Edit: creating a temp table did the job, however I have problems with passing output pareters.
CREATE PROCEDURE [dbo].[sprocB] (#prm INT = NULL OUTPUT)
AS
BEGIN
SET NOCOUNT ON;
SET #prm = 1
SELECT Id FROM dbo.AnyTable
END
CREATE PROCEDURE [dbo].[sprocA] (#prm INT = NULL OUTPUT)
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #temp (Id INT)
INSERT INTO #temp
EXEC sprocB #prm
SELECT Id FROM #temp
END
To execute:
USE [MyDatabase]
GO
DECLARE #return_value int,
#prm int
EXEC #return_value = [dbo].[sprocA]
#prm = #prm OUTPUT
SELECT #prm as N'#prm'
SELECT 'Return Value' = #return_value
GO
The results from temp table are ok, resultset is retrieved correctly, however #pem value is still NULL.
It is possible but you need an auxiliary table:
CREATE PROCEDURE procB
AS
declare #table table (CalculatedField1 int, CalculatedField12 int)
insert into #table
EXEC sp_a
select SUM(CalculatedField1), SUM(CalculatedField2)
from #table
GO
This might do what you want:
create table #scratch (CalculatedField1 int, CalculatedField2 int,...)
insert into #scratch (exec procA params)
select sum(CalculatedField1), sum(CalculatedField2),... from #scratch
drop table #scratch

Dynamic insert into variable table statement SQL Server

I have a variable table:
DECLARE #A_Table TABLE(ID INT, att1 VARCHAR(100), att2 nvarchar(200))
I want to make dynamic sql, so I insert into this table some data (all inside a loop):
WHILE (#i <= 100) BEGIN
SELECT #other_att = NAME FROM #other_Table where ID = #i;
SET #sql = 'INSERT ' + #A_Table+ '(ID,att1,att2) SELECT '+CAST(#i AS VARCHAR)+' , '''+ #other_att+''', SUM('+ #other_att') FROM '+ #EVEN_OTHER_Table;
EXEC (#sql);
END
sql every time would look like:
INSERT INTO #A_Table SELECT 1 , 'subject', SUM(subject)
INSERT INTO #A_Table SELECT 2 , 'age', SUM(age)
INSERT INTO #A_Table SELECT 3 , 'sex', SUM(sex)....
AND after executing this :
SO I will get:
#A_Table:
id att1 att2
1 subject 4.3
2 age 4.5
3 sex 4.1
but I get an error:
Msg 137, Level 16, State 1, Line 48
Must declare the scalar variable "#A_Table".
SO what is it the syntax to insert dynamically into a variable table?
Ok I have understood it.
You could use the INSERT ... EXEC syntax to insert the data returned by the dynamic SELECT. Of course, you would then need to remove the INSERT part from the dynamic statement.
WHILE (#i <= 100) BEGIN
SELECT #other_att = NAME FROM #other_Table where ID = #i;
SET #sql = 'SELECT '+CAST(#i AS VARCHAR)+' , ''' + #other_att+''', SUM('+ #other_att + ') FROM '+ #EVEN_OTHER_Table;
INSERT INTO #A_Table (ID,att1,att2)
EXEC (#sql);
END
You have a table variable, not a variable that contains the table name.
So you would need the following.
WHILE (#i <= 100) BEGIN
SELECT #other_att = NAME FROM #other_Table where ID = #i;
SET #sql = 'INSERT INTO #A_Table (ID,att1,att2) SELECT '+CAST(#i AS VARCHAR)+' , '''+ #other_att+''', SUM('+ #other_att') FROM #EVEN_OTHER_Table';
EXEC (#sql);
END
You would also need to declare the table variable as a statement inside the #sql variable, and execute your declare table and inserts together, or use a local/global temporary table.
With a local temporary table (stored in the tempdb) you could do something like this.
CREATE TABLE #testtbl (ID INT);
EXEC ('INSERT INTO #testtbl VALUES (1)');
SELECT * FROM #testtbl
DROP TABLE #testtbl
Some good info about temporary tables in BOL
http://msdn.microsoft.com/en-us/library/ms174979.aspx - quite far down the page
And the table type.
http://msdn.microsoft.com/en-us/library/ms175010.aspx
Your EXEC statement occurs in a different context and is therefore unaware of any variables created in your original context.
To create dynamic insert query it is really a task, I also struggle to find it ,finally I have tried in the following way and it's successfully working. Please find the code below.
CREATE PROCEDURE [dbo].[InsertTodaysData] (#tbl varchar(50),#Days int,
#MDate varchar(50), #EValue varchar(50), #Speed varchar(50),
#Totalreturn varchar(50),#Closingv varchar(50), #TotalReturnV varchar(50))
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #SQLQuery varchar(2000)
-- Insert statements for procedure here
set #SQLQuery = 'INSERT INTO '+#tbl+' (ID,MDate,EValue,Speed,TotalReturnRatio,ClosingValue,
TotalReturnValue) VALUES ('+#Days+','''+#MDate+''', '+#EValue+', '+#Speed+',
'+#Totalreturn+', '+#Closingv+', '+#TotalReturnV+')'
EXECUTE(#SQLQuery)
END
Hope this will help you..