Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Syntax for identity-insert FROM with no columns to insert?

I have defined the following tables

CREATE TABLE dbo.T_Comments_Paths
(
     path_id bigint IDENTITY(1,1) NOT NULL
    ,CONSTRAINT [PK_T_Comments_Paths] PRIMARY KEY(path_id)
);


CREATE TABLE dbo.T_Comments 
(
     COM_Id int IDENTITY(1,1) NOT NULL 
    ,COM_Text NATIONAL CHARACTER VARYING(255) NULL 
    ,CONSTRAINT [PK_T_Comments] PRIMARY KEY(COM_Id)
);

If I need to get a path-id for a comment, for a single-value, I can get it like this:

DECLARE @outputTable TABLE (path_id bigint); 
INSERT INTO T_Comments_Paths OUTPUT INSERTED.path_id INTO @outputTable DEFAULT VALUES; 
SET @__pathuid = (SELECT TOP 1 id FROM @outputTable); 

However, I fail to find the syntax for getting the inserted ids (multiple) for an insert from another table.

e.g. I want to do this:

DECLARE @outputTable TABLE (path_id bigint, com_id bigint); 
INSERT INTO T_Comments_Paths
OUTPUT INSERTED.path_id, com_id INTO @outputTable DEFAULT VALUES  
FROM T_Comments 

this yields

"Incorrect syntax near FROM-keyword"

How can I do that (without cursor) ?
Note: I need to be compatible with MySQL, so I can't use newid(), because there's no uuid-type in MySQL, and I don't want to use varchar or varbinary either...

like image 423
Stefan Steiger Avatar asked Dec 12 '16 12:12

Stefan Steiger


People also ask

What is an identity column in insert statements?

An identity column contains a unique numeric value for each row in the table. Whether you can insert data into an identity column and how that data gets inserted depends on how the column is defined.

What is insert syntax in SQL?

INSERT INTO Syntax Specify both the column names and the values to be inserted: INSERT INTO table_name (column1, column2, column3, ...) VALUES (value1, value2, value3, ... );

Can we insert 0 in identity column?

The identity column is there to be computed at the time you insert into the table. If you set IDENTITY_INSERT ON you allow inserts on the identity column: you push 0, you get 0.


1 Answers

If I understand correctly, your problem boils down to this: Adding n new rows to a identity column and then bring those newly added values to update an empty column in a table with n rows (@outputTable) without worrying about matching.

Setting up for testing

CREATE TABLE #T_Comments_Paths (
    path_id BIGINT IDENTITY(1,1) NOT NULL
    , CONSTRAINT [PK1] PRIMARY KEY (path_id)
);

CREATE TABLE #T_Comments (
    com_id BIGINT IDENTITY(1,1) NOT NULL
    , com_text NVARCHAR(20) NULL
    , CONSTRAINT [PK2] PRIMARY KEY (com_id)
);

INSERT INTO #T_comments (com_text)
VALUES
('com1')
, ('com2');

**SOLUTION 1 **

If you are willing to add an extra column to the @outputTable (aka rowNo), you can get a shorter solution like this:

--Add a few values to make #T_Comment_Paths not empty, for testing purpose, making things not matching
INSERT INTO #T_Comments_Paths DEFAULT VALUES;
INSERT INTO #T_Comments_Paths DEFAULT VALUES;
INSERT INTO #T_Comments_Paths DEFAULT VALUES;

DECLARE @currentID BIGINT;
SELECT @currentID = IDENT_CURRENT('#T_Comments_Paths');
-- @currentID should be 3

DECLARE @outputTable TABLE (path_id bigint, com_id bigint, rowNo bigInt); 

INSERT INTO @outputTable (com_id, rowNo)
SELECT
    com_id
    , ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM
    #T_comments;

MERGE #T_Comments_Paths tgt
USING @outputTable src
ON tgt.path_id = src.path_id
WHEN NOT MATCHED THEN INSERT DEFAULT VALUES;

MERGE @outputTable tgt
USING (
    SELECT
        path_id
        , ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RowNo
    FROM
        #T_Comments_Paths
    WHERE
        path_id > @currentID
) src
ON tgt.RowNo = src.RowNo
WHEN MATCHED THEN UPDATE SET
    tgt.path_id = src.PATH_ID;

SELECT *
FROM
    @outputTable;

SELECT *
FROM
    #T_Comments_Paths

DROP TABLE #T_Comments;
DROP TABLE #T_Comments_Paths;

**SOLUTION 2 **

If you insist on only have 2 columns in the @outputTable, then this is a solution (longer)

--Add a few values to make #T_Comment_Paths not empty, for testing purpose
INSERT INTO #T_Comments_Paths DEFAULT VALUES;
INSERT INTO #T_Comments_Paths DEFAULT VALUES;
INSERT INTO #T_Comments_Paths DEFAULT VALUES;
DECLARE @currentID BIGINT;
SELECT @currentID = IDENT_CURRENT('#T_Comments_Paths');
-- @currentID should be 3

DECLARE @outputTable TABLE (path_id bigint, com_id bigint); 
DECLARE @outputMiddleTable TABLE (rowNo bigint, com_id bigint);


INSERT INTO @outputTable (com_id)
SELECT
    com_id
FROM
    #T_comments;

WITH cte AS (
    SELECT
        com_id
        , ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RowNo
    FROM
        @outputTable
)
INSERT INTO @outputMiddleTable (rowNo,com_id)
SELECT RowNo, com_id
FROM cte;

MERGE #T_Comments_Paths tgt
USING @outputTable src
ON tgt.path_id = src.path_id
WHEN NOT MATCHED THEN INSERT DEFAULT VALUES;

WITH cte1 AS (
SELECT
    path_id
    , ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RowNo
FROM
    #T_Comments_Paths
WHERE
    path_id > @currentID
), cte2 AS (
SELECT
    cte1.path_id
    , t1.com_id
FROM
    @outputMiddleTable t1
    JOIN cte1 ON t1.rowNo = cte1.RowNo
)
UPDATE ot
SET path_id = cte2.path_id
FROM @outputTable ot
    JOIN cte2 ON ot.com_id = cte2.com_id

SELECT *
FROM
    @outputTable;


DROP TABLE #T_Comments;
DROP TABLE #T_Comments_Paths;
like image 148
DVT Avatar answered Oct 20 '22 23:10

DVT