Inserting Values Into Table with Identity Column via Databricks - sql

I've created a table in Databricks that is mapped to a table hosted in an Azure SQL DB. I'm trying to do a very simple insert statement on a small table, but an identity column is giving me issues. This table has the aforementioned identity column and three additional columns.
I first tried something similar to below:
%sql
INSERT INTO tableName (col2, col3, col4)
VALUES (1, 'Test Value', '2018-11-16')
That was giving me a syntax error, so I did some searching and learned that Hive SQL doesn't allow you to specify columns for an INSERT statement. So then I tried something like below as a test:
%sql
INSERT INTO tableName
VALUES (100, 1, 'Test Value', '2018-11-16')
That gives me an error message that I can't insert explicit values into an identity column, but that's what I expected to happen.
If I can't specify the columns for my INSERT statement, how do I avoid issues when I have an identity column? I just want to insert values for the non-identity columns, and I want the ID column to continue incrementing like normal. The above example is extremely watered-down. I will need to do much larger insertions based on SELECT statements eventually, so any solution involving toggling on IDENTITY_INSERT probably isn't feasible.

Below is how we can create a table with an identity column -
CREATE TABLE table_name
(column_name1 data_type GENERATED ALWAYS AS IDENTITY,
column_name2......)
Below are the two ways how we can insert the data into the table with the Identity column -
First way -
INSERT INTO T2 (CHARCOL2)
SELECT CHARCOL1 FROM T1;
Second way -
INSERT INTO T2 (CHARCOL2,IDENTCOL2) OVERRIDING USER VALUE
SELECT * FROM T1;
Links for reference-
Create table - https://docs.databricks.com/sql/language-manual/sql-ref-syntax-ddl-create-table-using.html
Insert into table - https://www.ibm.com/docs/en/db2-for-zos/11?topic=statement-rules-inserting-data-into-identity-column

Related

SQL Server Insert Into Table containing a column "Timestamp (Rowversion)"

I'm creating a C# Winforms application for recipe management in an industrial environment.
I created a SQL Server table with 130 columns. The table contains a column called CheckData (of datatype Timestamp), which I use to detect changes made to a row.
If I insert a new row to that table all works fine. The code I use is:
INSERT INTO tablename (Column1, column2, column3, column4)
VALUES (value1, value2, value3, value4)
I just assign values to major columns, the others get their default value. I do not assign a value to the timestamp field since it's written by the system.
Additionally, I want to copy a row from this table to the same table (duplicate a data record).
I copy the source row to a temporary table, drop the ID (primary key) and the timestamp fields in that temporary table and try to insert that only row in the temporary table into the table. This fails.
Here's the code:
SELECT *
INTO #temptable
FROM tablename
WHERE Recipe_No = 8;
ALTER TABLE #temptable DROP COLUMN ID, CHECKDATA;
ALTER TABLE #temptable REBUILD;
UPDATE #temptable
SET Recipe_No = 9, Recipe_Name = 'Test'
WHERE Recipe_No = 8;
INSERT INTO tablename
SELECT * FROM #temptable;
I don't understand where the difference is between inserting a new row thru INSERT INTO xxx (yyy) VALUES (zzz) and INSERT INTO xxx SELECT * FROM yyy. In both cases I don't try to write the timestamp value in the new row.
Does anybody have an idea what I'm missing here?
I don't understand where the difference is between inserting a new row thru INSERT INTO xxx (yyy) VALUES (zzz) and INSERT INTO xxx SELECT * FROM yyy.
With this,
INSERT INTO xxx SELECT * FROM yyy.
you are failing to specify the column mappings from the SELECT to the target table. You should always use
INSERT INTO xxx (Column1, Column2, . . .)
SELECT (Column1, Column2, . . .)
FROM yyy
Here's a simplified example of what you're attempting:
drop table if exists t
create table t(id int, a int)
insert into t(id,a) values (1,1)
select * into #t from t where id = 1
alter table #t drop column id
insert into t select * from #t
and it will fail with
Msg 213, Level 16, State 1, Line 12
Column name or number of supplied values does not match table definition.
because the temp table doesn't even have the same number of columns. And even if it did, you wouldn't know for sure that the column mappings were correct.
It is failing because essentially your command
INSERT INTO tablename SELECT * FROM #temptable;";
Is telling SQL - "Insert everything into this table from this temp table."
While you can work around this, I would say why don't you just try inserting into only the columns made available in your current table with only the values you would like to include. Instead of needing to drop the columns/values, you just don't import it to begin with.
An alternative - if you can write to a helper table, it may be beneficial to INSERT INTO that helper table, as opposed to a temp table, the values you have. Then transform that helper table, and THEN you can do INSERT INTO final_table SELECT * FROM helper. This should give you the results you're looking for.
I hope this is helpful, and I hope it explains why your current command is failing.

Creating New GUID automatically while inserting a new row to an existing table Not Working

I have an existing table in MS SQL called myTab.
It has the following fields
empno(PK) nchar(10),
age int
Now, i want to add a myGUID column and fill it up with a GUID whenever i insert a new row as well as Updating existing rows.
So i added the statement
ALTER TABLE myTab ADD myGUID uniqueidentifier DEFAULT NewId() NOT NULL;
Updating existing rows works correctly.
But, when i try to insert values,
INSERT INTO myTab VALUES ( 1000, 22 );
It fails, and gives the following message
**Column name or number of supplied values does not match table definition.**
When i do
insert into sourav_test2 values (20055711,23,NEWID());
The above statement works.
I want a GUID to be filled without changing the insert statement. Is it possible via a Trigger or a Function?
Always list the columns you are inserting!
INSERT INTO myTab (empno, age)
VALUES ('1000', 22);
Also use correct types for the values. Unmentioned columns will be assigned their default values, or NULL if there is no explicit default.
Your table has three columns, so if you leave out the column list, then the insert expects three values. You can still set a default, if you want by using the DEFAULT keyword in the VALUES clause:
INSERT INTO myTab (empno, age, myGUID)
VALUES ('1000', 22, DEFAULT);
Sourav's question about triggers got me thinking, so I tried a little test. Why?
Imagine a scenario where an application has already been written with thousands of INSERT statements that leave off the column list. In this case, if you could write an INSTEAD OF INSERT trigger that provides the column list, you could hopefully save yourself from correcting thousands of INSERT statements due to a newly added column.
Off the top of my head, I admittedly did not know if this could work.
So I wrote this little test:
CREATE TABLE tt (ColA varchar(1));
INSERT INTO tt VALUES ('a');
ALTER TABLE tt
ADD ColB uniqueidentifier DEFAULT NEWID();
GO
CREATE TRIGGER tr_tt
ON tt
INSTEAD OF INSERT
AS
INSERT INTO tt (ColA)
SELECT ColA FROM inserted;
GO
INSERT INTO tt VALUES ('a');
SELECT * FROM tt;
DROP TABLE tt;
I also tried a variation of the TRIGGER with the following INSERT just to be thorough:
INSERT INTO tt (ColA, ColB)
SELECT ColA, NEWID() FROM inserted;
The result was the same in both cases: The same error as reported in the question. So to answer the question:
Can't we use a trigger here which can do it?
The answer is NO. Even if you put an INSTEAD OF INSERT TRIGGER on the table, the parser will still not let you write an INSERT..VALUES() statement unless the number and order of VALUES exactly matches the definition of the table. A TRIGGER cannot be used to get around it.
Sooner or later, lazy coding exacts its price.

Insert into table from a temp table without identity column ?

I need to insert into table with same column in temp table. without identity column of table which am inserting.
Remaining columns of inserting table is contained in temp table.
You need to be able to generate primary key values on your own. With IBM DB2, I am using sequences to get those values. It would be good to know which RDBMS you are using.
A statement matching your needs could look like that:
INSERT INTO MYSCHEMA.MYTABLE
select (NEXTVAL FOR MYSCHEMA.ID_SEQUENCE) as ID, T.*
from MYSCHEMA.MYTEMPTABLE T

Can't INSERT INTO SELECT into a table with identity column

In SQL server, I'm using a table variable and when done manipulating it I want to insert its values into a real table that has an identity column which is also the PK.
The table variable I'm making has two columns; the physical table has four, the first of which is the identity column, an integer IK. The data types for the columns I want to insert are the same as the target columns' data types.
INSERT INTO [dbo].[Message] ([Name], [Type])
SELECT DISTINCT [Code],[MessageType]
FROM #TempTableVariable
This fails with:
Cannot insert duplicate key row in object 'dbo.Message' with unique index
'IX_Message_Id'. The duplicate key value is (ApplicationSelection).
But when trying to insert just Values (...) it works ok.
How do I get it right?
It appears that the data "ApplicationSelection" is already in the database. YOu need to write the select to exclude records that are already in the database. YOu can do that with a where not exists clause or a left join. LOok up teh index to see what field is unique besides the identity. That will tell you what feild you need to check to see if teh record currently exists.

large insert in two tables. First table will feed second table with its generated Id

One question about how to t-sql program the following query:
Table 1
I insert 400.000 mobilephonenumbers in a table with two columns. The number to insert and identity id.
Table 2
The second table is called SendList. It is a list with 3columns, a identity id, a List id, and a phonenumberid.
Table 3
Is called ListInfo and contains PK list id. and info about the list.
My question is how should I using T-sql:
Insert large list with phonenumbers to table 1, insert the generated id from the insert of phonenum. in table1, to table 2. AND in a optimized way. It cant take long time, that is my problem.
Greatly appreciated if someone could guide me on this one.
Thanks
Sebastian
What version of SQL Server are you using? If you are using 2008 you can use the OUTPUT clause to insert multiple records and output all the identity records to a table variable. Then you can use this to insert to the child tables.
DECLARE #MyTableVar table(MyID int);
INSERT MyTabLe (field1, field2)
OUTPUT INSERTED.MyID
INTO #MyTableVar
select Field1, Field2 from MyOtherTable where field3 = 'test'
--Display the result set of the table variable.
Insert MyChildTable (myID,field1, field2)
Select MyID, test, getdate() from #MyTableVar
I've not tried this directly with a bulk insert, but you could always bulkinsert to a staging table and then use the processs, described above. Inserting groups of records is much much faster than one at a time.