Adding result of column expression as new column on table variable creation - sql

I'm sure this is really easy but I can't think of a solution and can't seem to find any documentation that answers my exact question.
While inserting values into a table variable how do I set the value of a field to be the result of an expression from another field in the same table?
For example:
declare #tableVar table(
[col1] int,
[col2] dec(18,2),
[col3] dec(18,2)
)
insert into #tableVar
values (100,.03,[col1] * [col2])
select *
from #tableVar
Would ideally return:
col1 col2 col3
100 0.03 3.00
But I get this error instead:
Msg 207, Level 16, State 1, Line 19
Invalid column name 'col1'.
Msg 207, Level 16, State 1, Line 19
Invalid column name 'col2'.
I understand why I get the error I just can't seem to come up with a solution.
Any hints?

You would use a subquery:
insert into #tableVar (col1, col2, col3)
select col1, col2, col1 * col2
from (values (100, 0.03)) v(col1, col2);
Or, better yet, use a computed column:
declare #tableVar table (
col1 int,
col2 dec(18, 2),
col3 as ( convert(dec(18, 2), col1 * col2) )
);
insert into #tableVar (col1, col2)
values (100, 0.03);
Note that both these examples explicitly list the columns being inserted. That is considered a best-practice.

You need values construct :
insert into #tableVar (col1, col2, col3)
select col1, col2, col1 * col2
from (values (100, .03)
) t(col1, col2);

Related

Get ID of inserted & Selected row after multiple insert [duplicate]

This question already has answers here:
Insert Into... Merge... Select (SQL Server)
(1 answer)
Combine OUTPUT inserted.id with value from selected row
(2 answers)
Closed 4 years ago.
I have a query running in loop which I am trying to optimize as this
INSERT INTO myTable (col1, col2, col3)
OUTPUT inserted.id, SOURCE_ROW_ID_NEEDED_HERE
SELECT col1, col2, col3
FROM myTable
WHERE col2 = 20 --any value
My problem is : col2 = 20 can have N number of rows which get inserted, I need the id of the source row for the new record. For example say there are 3 rows for col2 = 20 and id of them are 11,12,15. The new inserted ID are say 150,151,152.
I would need
11 150
12 151
15 152
Are you looking for something like
CREATE TABLE T1(
Col1 INT IDENTITY(1, 1),
Col2 INT,
Col3 INT
);
CREATE TABLE T2(
Col1 INT IDENTITY(1, 1),
Col2 INT,
Col3 INT
);
INSERT INTO T2(Col2, Col3) VALUES
(11, 150),
(12, 151),
(15, 152);
DECLARE #TT TABLE (ID INT, Col2 INT);
SET IDENTITY_INSERT T1 ON;
INSERT INTO T1 (Col1, Col2, Col3)
OUTPUT INSERTED.Col1,
INSERTED.Col2
INTO #TT (ID, Col2)
SELECT Col1,
Col2,
Col3
FROM T2;
SELECT *
FROM #TT;
SET IDENTITY_INSERT T1 OFF;
Demo

Convert each column of a record into separate record

I have a record:
DECLARE #Tbl AS TABLE(Col1 VARCHAR(10), Col2 VARCHAR(10), Col3 VARCHAR(10));
INSERT INTO #Tbl
VALUES('Val1', 'Val2', 'Val3')
-- Source Record
SELECT Col1, Col2, Col3 FROM #Tbl
Result: Val1 Val2 Val3
I want result of each column as separate two column records like first column will become the title of source column and second column should be the value of source column like the result of below query in which I have achieved the result by UNION ALL :
--Query for Target Result
SELECT 'Col1' AttributeTitle, CONVERT(VARCHAR, Col1) AttributeValue FROM #Tbl
UNION ALL SELECT 'Col2' AttributeTitle, CONVERT(VARCHAR, Col2) AttributeValue FROM #Tbl
UNION ALL SELECT 'Col3' AttributeTitle, CONVERT(VARCHAR, Col3) AttributeValue FROM #Tbl
Problem in this query is I have to explicitly define the columns, is there any way that it should dynamically get the columns names and their values?
You could use UNPIVOT but you still need to know the names of the columns.
SELECT ColumnName, ValueName
FROM (SELECT * FROM #Tbl) AS Data
UNPIVOT
( ValueName
FOR ColumnName IN (Col1, Col2, Col3)
) AS PivottedOutput
I like the apply method for unpivoting in SQL Server:
select v.*
from #tbl t cross apply
(values ('col1', col1),
('col2', col2),
('col3', col3)
) v(AttributeTitle, AttributeValue);
This simplifies the query but it does not directly answer the question.
If you want a variable number of columns, then you are going to have to use dynamic SQL. This is a bit cumbersome on a real table. However, with a table variable or a temporary table, you have the additional issue of scoping rules -- the name of the table will not be in scope when you execute the statement.

Insert into a table using values from another

I am trying to perform an insert using the following command:
insert into table2(COL1, COL2, COL3, COL4) values((select COL1 FROM table1 WHERE COL1 = 121212),120,10,"Y");
But I get the following error:
ERROR at line 1: ORA-00984: column not allowed here
Any help?
INSERT INTO table2( col1, col2, col3, col4 )
SELECT col1, 120, 10, 'Y'
FROM table1
WHERE col1 = 121212
should work.

Using the dangerous IN clause in SQL

Why does SQL server behave this way. I am running this on SQL 2005.
The IN clause does not validate the column names in the sub query but validates it
against the table name in the outer query. Here is an example of getting
Create table #table1(col1 int, col2 char(10), col3 char(15));
Create table #table2(col10 int, col11 char(10), col2 char(15));
insert into #table1(col1, col2, col3)
select 1, 'one', 'three'
insert into #table1(col1, col2, col3)
select 2, 'two', 'three'
insert into #table1(col1, col2, col3)
select 3, 'three', 'four'
insert into #table2(col10, col11, col2)
select 1, 'one', 'three'
insert into #table2(col10, col11, col2)
select 2, 'two', 'three'
insert into #table2(col10, col11, col2)
select 3, 'three', 'four'
select * from #table1
where col1 IN
(select col1 from #table2)
Where as if I just select the "select col1 from #table2" and run it spits an error
Msg 207, Level 16, State 1, Line 1
Invalid column name 'col1'.
Why? Because it's frequently useful to be able to reference columns from the outer query in subqueries. There's no setting you can use to turn off this behaviour, but if you get into the habit of using aliases, you should avoid most problems with it:
select * from #table1 t1
where t1.col1 IN
(select t2.col1 from #table2 t2)
Will produce an error.
It's not the IN clauses that's the problem.
This:
SELECT *
FROM #table1
WHERE col1 IN (SELECT col1
FROM #table2)
...works, because the optimizer is assumes col1 to be from #table1. If you use table aliases so there's no ambiguity:
SELECT t1.*
FROM #table1 t1
WHERE t1.col1 IN (SELECT t2.col1
FROM #table2 t2)
...you'll get the Msg 207: Invalid column error.
This is the same principle as when working with DELETE and UPDATE statements, because the typical syntax doesn't allow you to alias the table being deleted or updated.

How to convert a column header and its value into row in sql?

I have a table with columns say col1, col2, col3. The table has many rows in it.
Let's assume val1, val2, val3 is one such row. I want to get the result as
Col1, Val1
Col2, Val2
Col3, Val3
That is 3 rows - one for each column and its value.
I am using SQL Server 2008. I read about pivots. Are pivots a way to solve this problem? Can someone route me to some examples or solutions how to solve this problem?
Thanks a lot
Maybe something like this:
Test data
DECLARE #T TABLE(Col1 INT, Col2 INT, Col3 INT)
INSERT INTO #T
VALUES (1,1,1)
Query
SELECT
*
FROM
(
SELECT
t.Col1,
t.Col2,
t.Col3
FROM
#T AS t
) AS SourceTable
UNPIVOT
(
Value FOR Col IN
(Col1,Col2,Col3)
) AS unpvt
Output
1 Col1
1 Col2
1 Col3
To do this kind of thing read the following: Using PIVOT and UNPIVOT
Pivot function allow you to convert row values in from of column..
Also check : Dynamic Pivoting in SQL Server
Example :
create table #temptable(colorname varchar(25),Hexa varchar(7),rgb varchar(1), rgbvalue tinyint)
GO
insert into #temptable values('Violet','#8B00FF','r',139);
insert into #temptable values('Violet','#8B00FF','g',0);
insert into #temptable values('Violet','#8B00FF','b',255);
insert into #temptable values('Indigo','#4B0082','r',75);
insert into #temptable values('Indigo','#4B0082','g',0);
insert into #temptable values('Indigo','#4B0082','b',130);
insert into #temptable values('Blue','#0000FF','r',0);
insert into #temptable values('Blue','#0000FF','g',0);
insert into #temptable values('Blue','#0000FF','b',255);
SELECT colorname,hexa,[r], [g], [b]
FROM
(SELECT colorname,hexa,rgb,rgbvalue
FROM #temptable) AS TableToBePivoted
PIVOT
(
sum(rgbvalue)
FOR rgb IN ([r], [g], [b])
) AS PivotedTable;
Create a temproary table:
CREATE TABLE #table2
(
name NCHAR,
bonus INT
)
Now Select and execute the below statement if there is an empty.
SELECT * FROM #table2
INSERT INTO #table2 (name,bonus) VALUES ('A',10)
INSERT INTO #table2 (name,bonus) VALUES ('B',20)
INSERT INTO #table2 (name,bonus) VALUES ('C',30)
After insert the values into table. select and execute the below line if you get records:
SELECT * FROM #table2
Input:
name bonus
A 10
B 20
C 30
Change the input into like this result
Result:
Cost A B C
Bonus 10 20 30
By using this code:
SELECT 'Bonus' AS Cost,
[A],[B],[C]
FROM
(SELECT name, Bonus
FROM #table2) AS TempTbl
PIVOT
(
AVG(bonus)
FOR [name] IN ([A],[B],[C])
) AS PivotTable;