Insert Multiple Rows SQL Teradata - sql

I am creating a volatile table and trying to insert rows to the table. I can upload one row like below...
create volatile table Example
(
ProductID VARCHAR(15),
Price DECIMAL (15,2)
)
on commit preserve rows;
et;
INSERT INTO Example
Values
('Steve',4);
However, when I try to upload multiple I get the error:
"Syntax error: expected something between ')' and ','."
INSERT INTO Example
Values
('Steve',4),
('James',8);

As Gordon said, Teradata doesn't support VALUES with multiple rows (and the UNION ALL will fail because of the missing FROM.
You can utilize a Multi Statement Request (MSR) instead:
INSERT INTO Example Values('Steve',4)
;INSERT INTO Example Values('James',8)
;
If it's a BTEQ job the Inserts are submitted as one block after the final semicolon (when there's a new command starting on the same line it's part of the MSR). In SQL Assistant or Studio you must submit it using F9 instead of F5.

I don't think Teradata supports the multiple row values syntax. Just use select:
INSERT INTO Example(ProductId, Price)
WITH dual as (SELECT 1 as x)
SELECT 'Steve' as ProductId, 4 as Price FROM dual UNION ALL
SELECT 'James' as ProductId, 8 as Price FROM dual;

CTE syntax (working):
insert into target_table1 (col1, col2)
with cte as (select 1 col1)
select 'value1', 'value2' from cte
union all
select 'value1a', 'value2a' from cte
;
CTE Syntax not working in Teradata
(error: expected something between ")" and the "insert" keyword)
with cte as (select 1 col1)
insert into target_table1 (col1, col2)
select 'value1', 'value2' from cte
union all
select 'value1a', 'value2a' from cte
;

I found a solution for this via RECURSIVE. It goes like this:-
INSERT INTO table (col1, col2)
with recursive table (col1, col2) as
(select 'val1','val2' from table) -- 1
select 'val1','val2' from table -- 2
union all select 'val3','val4' from table
union all select 'val5','val6' from table;
Data of line 1 does not get inserted (but you need this line). Starting from line 2, the data you enter for val1, val2 etc. gets inserted into the respective columns. Use as many UNION ALLs' as many rows you want to insert. Hope this helps :)

At least in our version of Teradata, we are not able to use an insert statement with a CTE. Instead, find a real table (preferably small in size) and do a top 1.
Insert Into OtherRealTable(x, y)
Select top 1
'x' as x,
'y' as y
FROM RealTable

create table dummy as (select '1' col1) with data;
INSERT INTO Student
(Name, Maths, Science, English)
SELECT 'Tilak', 90, 40, 60 from dummy union
SELECT 'Raj', 30, 20, 10 from dummy
;

yes you can try this.
INSERT INTO Student
SELECT (Name, Maths, Science, English) FROM JSON_Table
(ON (SELECT 1 id,cast('{"DataSet" : [
{"s":"m", "Name":"Tilak", "Maths":"90","Science":"40", "English":"60" },
{"s":"m", "Name":"Raj", "Maths":"30","Science":"20", "English":"10" }
]
}' AS json ) jsonCol)
USING rowexpr('$.DataSet[*]')
colexpr('[{"jsonpath":"$.s","type":"CHAR(1)"},{"jsonpath":"$.Name","type":"VARCHAR(30)"}, {"jsonpath":"$.Maths","type":"INTEGER"}, {"jsonpath":"$.Science","type":"INTEGER"}, {"jsonpath":"$.English","type":"INTEGER"}]')
) AS JT(id,State,Name, Maths, Science, English)

Related

"ORA-00984: column not allowed here" when inserting with select statement

I would like to insert some data into a table. One field I would like to get from another table, so I'm using select statement inside. This is the code:
INSERT INTO t.table1 (
id,
id_t2,
date_of_change
)
VALUES (
t.table1_seq.nextval,
SELECT s.id_id_t2 from t.table2 s where s.something='something',
TO_DATE('02/05/2017 13:43:34','DD/MM/YYYY HH24:MI:SS')
)
Although select statement is always returning only 1 field (1 row), I presume this is why I'm getting the error.
How can I write INSERT statement with SELECT statement for just 1 field? Can it be done? If not, is there any other solution for this problem? Thank you.
You can translate your whole insert statement into the form of
insert into table1 (fields)
select fields from table2
This will allow you to specify in your select some values from the source table and some constant values. Your resulting query would be
INSERT INTO t.table1 (
id,
id_t2,
date_of_change
)
SELECT t.table1_seq.nextval,
s.id_id_t2,
TO_DATE('02/05/2017 13:43:34','DD/MM/YYYY HH24:MI:SS')
FROM t.table2 s
WHERE s.something='something'

Vertica - Work around for using WITH with INSERT statement

I have a SQL query like
with subtable as (
................
)
select *
from subtable
I wanted to insert the records from the select statement into a table. looking for something like :
with subtable as (......)
insert into newtable
select *
from subtable
However, in Vertica, INSERT cannot be used with the WITH ( CTE) statements.
Is there any work around for this?
Thanks for the help
with is part of the select.
insert into newtable
with subtable as (......)
select *
from subtable
I can only agree to what woot said.
In Vertica, the common table expression is supported in the SELECT statement - not in any DML statement. That's also what the ANSI standard intended.
If your point is to have the data bit at the top of the script and not "hidden" by the INSERT INTO foo line before, then you can (but still with one line before the WITH clause):
CREATE LOCAL TEMPORARY TABLE foo(id,ts,name,exp) ON COMMIT PRESERVE ROWS AS
SELECT 1,'2016-12-13 10:11'::TIMESTAMP,'Moshe',1
UNION ALL SELECT 2,'2016-12-13 12:12'::TIMESTAMP,'Karl' ,2
UNION ALL SELECT 3,'2016-12-13 13:12'::TIMESTAMP,'Karl' ,2
UNION ALL SELECT 4,'2016-12-13 14:09'::TIMESTAMP,'Moshe',2
UNION ALL SELECT 5,'2016-12-13 18:07'::TIMESTAMP,'Karl' ,2
KSAFE 0;
Marco the Sane

BLOB aggregation

I've got the table:
create table example (id number, image varchar2(10));
With 2 rows:
insert into example (24, 'pippo');
insert into example (35,'pluto');
The query is:
select max(case when id=24 then image end) as col1,
max(case when id=35 then image end) as col2
from example;
This works perfectly fine with column "image" as varchar2! The problem is that the column is a BLOB.
How can I produce the same output?
Take in mind that I need to pull out of the table 28 images (so 28 columns and one row).
Still not clear why you need the result in columns and not rows... perhaps you only think you do? Alex asked you the most important question: Who/what will call this and consume the results? How is the result set used in further processing? It is possible you don't actually need the results in columns.
In any case, you can use Alex's suggestion of having 28 subquery expressions. If your concern is with performance, you can first select into a CTE (a WITH clause), whose result set will have just 28 rows - and then write the subquery expressions against the CTE. Something like this:
with prep ( id, blob_col ) as (
select id, blob_col from base_table where id in (24, 35, ... )
)
select
(select blob_col from prep where id = 24) as col_1,
(select blob_col from prep where id = 35) as col_2,
...
from dual
;

How to insert multiple records using single insert statement in Teradata?

In teradata, can we insert multiple records using single insert statement in query. If yes, how ?
Say I am trying to do something like:
insert test_rank (storeid,prodid,sales) values (1,'A',1000) ( 2,'B',2000) ,(3,'C',3000);
but this is not working in teradata to insert all 3 records in one statement.
INSERT INTO test_rank (storeid, prodid, sales)
SELECT *
FROM (SELECT *
FROM (SELECT 0 storeid,
1 prodid,
2 sales) T1
UNION ALL
SELECT *
FROM (SELECT 3 storeid,
4 prodid,
5 sales) T2
UNION ALL
SELECT *
FROM (SELECT 6 storeid,
7 prodid,
8 sales) T3
...
)T;
Thanks, Rob! Your advice helped me.
If you are dealing with small data, you can try putting the values inside a text file and import them with the Teradata SQLA.
Create a text file consisting your input, delimited by a tab (use comma if tab doesn't work in your version):
1 A 1000
2 B 2000
3 C 3000
Then select the import mode on your SQLA, File -> Import Data, and run this following statement:
insert into YourTable values (?, ?, ?);
Make sure you create the table beforehand, with the correct data types.
I'm not sure how practical this will be but technically this following is possible:
INSERT INTO MyTable
SELECT *
FROM
( SELECT 1 AS StoreID
, 'A' AS ProdID
, 1000 AS SALES
UNION
SELECT 2
, 'B'
, 2000
SELECT 3
, 'C'
, 3000
) DT1
;
Secondly, if you are using BTEQ then you can look into the USING command combined with a flat file repeat single INSERT statement to load the table. But at that point you might as well leverage a proper load utility (MultiLoad or FastLoad) depending on the volumes to accomplish this task if you are doing anything with reasonable volume.
Edit - 2015-12-10
The SQL above will not run unless each SELECT in the UNION is first placed in a derived table. See the answer below from Anatoly for the correct syntax.
Sometimes is useful to create table with data rather than try to make complicated dynamical insert.
CREATE TABLE db.Inc_Config AS (
SELECT
c.calendar_date,
null as Sent_To,
CURRENT_TIMESTAMP as Sent_Date,
date '2016-01-01' as Inc_Start_Date,
date '2016-02-29' as Inc_End_Date
FROM sys_calendar.CALENDAR c
WHERE
c.calendar_date BETWEEN date '2016-01-01' AND date '2016-02-29'
) WITH data;

PostgreSQL: Select a single-row x amount of times

A single row in a table has a column with an integer value >= 1 and must be selected however many times the column says. So if the column had '2', I'd like the select query to return the single-row 2 times.
How can this be accomplished?
Don't know why you would want to do such a thing, but...
CREATE TABLE testy (a int,b text);
INSERT INTO testy VALUES (3,'test');
SELECT testy.*,generate_series(1,a) from testy; --returns 3 rows
You could make a table that is just full of numbers, like this:
CREATE TABLE numbers
(
num INT NOT NULL
, CONSTRAINT numbers_pk PRIMARY KEY (num)
);
and populate it with as many numbers as you need, starting from one:
INSERT INTO numbers VALUES(1);
INSERT INTO numbers VALUES(2);
INSERT INTO numbers VALUES(3);
...
Then, if you had the table "mydata" that han to repeat based on the column "repeat_count" you would query it like so:
SELECT mydata.*
FROM mydata
JOIN numbers
ON numbers.num <= mydata.repeat_count
WHERE ...
If course you need to know the maximum repeat count up front, and have your numbers table go that high.
No idea why you would want to do this thought. Care to share?
You can do it with a recursive query, check out the examples in
the postgresql docs.
something like
WITH RECURSIVE t(cnt, id, field2, field3) AS (
SELECT 1, id, field2, field3
FROM foo
UNION ALL
SELECT t.cnt+1, t.id, t.field2, t.field3
FROM t, foo f
WHERE t.id = f.id and t.cnt < f.repeat_cnt
)
SELECT id, field2, field3 FROM t;
The simplest way is making a simple select, like this:
SELECT generate_series(1,{xTimes}), a.field1, a.field2 FROM my_table a;