2016-12-12 41 views
7

I zostały zdefiniowane następujące tabeleSkładnia dla tożsamości-wstaw z FROM bez kolumn do wstawienia?

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) 
); 

Jeśli muszę dostać path-id o komentarz, dla pojedynczej wartości, mogę to tak:

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); 

jednak Nie mogę znaleźć składni do wstawiania identyfikatorów (wielokrotnych) dla wstawki z innej tabeli.

np. Chcę, aby to zrobić:

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 

to daje

"Niepoprawna składnia w pobliżu Z-słów kluczowych"

Jak mogę to zrobić (bez kursora)?
Uwaga: muszę być kompatybilne z MySQL, więc nie mogę używać newID(), ponieważ nie ma UUID typu MySQL, a nie chcę użyć varchar lub varbinary albo ...

+0

@ Starostin: Nie jest to duplikat, wstawia tylko jedną wartość. Znalazłem również ten wpis. Nie tego chcę. –

+0

Czy próbowałeś przedrostkiem com_id z INSERTED? Tak: OUTPUT INSERTED.path_id, INSERTED.com_id INTO @ outputTable DOMYŚLNE WARTOŚCI? –

+0

@John Joseph: Nie wstawiam com_id do T_Comments_Paths, po prostu włączam to do tabeli wyjściowej, razem z wygenerowanym autoid. –

Odpowiedz

1

Jeśli dobrze rozumiem, twój problem sprowadza się do tego: Dodanie n nowych wierszy do kolumny tożsamości, a następnie dodanie nowo dodanych wartości do aktualizacji pustej kolumny w tabeli zawierającej n wierszy (@ outputTable) bez obawy o dopasowanie.

Konfiguracja do testowania

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'); 

ROZWIĄZANIE 1 ** **

Jeśli są chętni, aby dodać dodatkową kolumnę w @outputTable (aka równo), można uzyskać krótszy rozwiązanie jak to:

--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; 

ROZWIĄZANIE 2 ** **

Jeśli domagać się tylko 2 kolumny w @ outputTable, to jest rozwiązanie (dłuższe)

--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; 
+1

W przypadku, gdy nie było to jasne: nalegam na 0 dodatkowych kolumn i dwóch kolumn wyjściowych, ściśle. Dodatkowa kolumna jest znacznie krótsza niż dowolne rozwiązanie, które dodaje dodatkową kolumnę. Również scalanie nie jest konieczne ani pożądane. To po prostu źródło błędów dla środowiska wielowątkowego. –

+0

Miałem na myśli dodatkową kolumnę do tabeli zmiennych outputTable, a nie oryginalną tabelę T_Comments_Paths (która w moich rozwiązaniach to #T_Comments_Paths). Wprowadziłem dwa rozwiązania, jeden z dodatkową kolumną w zmiennej outputTable, drugi bez dodatkowej kolumny w zmiennej outputTable (ale potrzebuje dodatkowej zmiennej tabeli) – DVT

+1

Nie sądzę, że ktokolwiek to czyta, zrozumie, co się dzieje. Tylko z tego powodu nie można go nazwać "rozwiązaniem". Ponadto nie widzę, jakie korzyści oferuje ten kursor nad kursorem. Jest dłuższy i bardziej skomplikowany. Próbuję napisać przenośny, niezależny od RDBMS kod, dlatego chcę, aby tak mało takich rzeczy było technicznie możliwych. Poszedł z dodatkową kolumną, ponieważ to jedyne rozwiązanie, które uniemożliwia takie rzeczy jak kursory czy to. Prawidłowa odpowiedź na to pytanie brzmi: "to niemożliwe". –