문제

이름-값 쌍 데이터의 테이블 저장을 SQL Server 2008의 관계형 양식으로 변환하고 싶습니다.

소스 테이블

Strings
ID  Type    String
100 1   John
100 2   Milton
101 1   Johny
101 2   Gaddar

대상이 필요합니다

Customers
ID  FirstName   LastName
100 John        Milton
101 Johny       Gaddar

아래에 주어진 전략을 따르고 있습니다.

문자열 테이블에서 ID 값으로 고객 테이블을 채우십시오.

INSERT INTO CUSTOMERS SELECT DISTINCT ID FROM Strings

당신은 다음을 얻습니다

Customers
ID  FirstName   LastName
100 NULL        NULL
101 NULL        NULL

ID 열을 사용하여 문자열에 가입하여 나머지 속성으로 고객을 업데이트하십시오. 이 방법으로 고객의 각 레코드에는 해당 2 개의 일치하는 레코드가 있습니다.

UPDATE Customers
    SET FirstName = (CASE WHEN S.Type=1 THEN S.String ELSE FirstName)
        LastName = (CASE WHEN S.Type=2 THEN S.String ELSE LastName)
FROM Customers
    INNER JOIN Strings ON Customers.ID=Strings.ID

중간 상태는 Like가 될 것입니다.

ID  FirstName   LastName    ID  Type    String
100 John        NULL        100 1   John
100 NULL        Milton      100 2   Milton
101 Johny       NULL        101 1   Johny
101 NULL        Gaddar      101 2   Gaddar

그러나 이것은 예상대로 작동하지 않습니다. 값을 할당 할 때 SET 절은 커밋되지 않은 대신 커밋 된 값 만 설정합니다. 어쨌든 커밋되지 않은 값 (쿼리 처리 시간에)을 설정할 수 있습니까? UPDATE 성명?

추신: 대체 솔루션을 찾고 있지는 않지만 SQL Server에게 커밋되지 않은 데이터를 사용하도록 지시하여 접근 방식을 작동시킵니다. UPDATE.

도움이 되었습니까?

해결책

이것을 살펴보면 모든 단계를 피해야합니다.

DECLARE @Table TABLE(
        ID INT,
        Type INT,
        String VARCHAR(50)
)
INSERT INTO @Table (ID,[Type],String) SELECT 100 ,1   ,'John'
INSERT INTO @Table (ID,[Type],String) SELECT 100 ,2   ,'Milton'
INSERT INTO @Table (ID,[Type],String) SELECT 101 ,1   ,'Johny'
INSERT INTO @Table (ID,[Type],String) SELECT 101 ,2   ,'Gaddar'

SELECT  IDs.ID,
        tName.String NAME,
        tSur.String Surname
FROM    (
            SELECT DISTINCT ID
            FROM @Table
        ) IDs LEFT JOIN
        @Table tName ON IDs.ID = tName.ID AND tName.[Type] = 1  LEFT JOIN
        @Table tSur ON IDs.ID = tSur.ID AND tSur.[Type] = 2

좋아, 나는 당신이 찾고있는 것에 대한 해결책을 찾을 것이라고 생각하지 않습니다. 에서 업데이트 (Transact-SQL) 그것은 말한다

From Clause와 함께 업데이트 사용

명령문에 업데이트 된 각 열 발생에 대해 하나의 값 만 사용할 수있는 방식으로 명시되지 않은 조항이 포함되어있는 경우 업데이트 문의 결과는 정의되지 않습니다. 즉, 업데이트 문이 결정적이지 않은 경우입니다. 예를 들어, 다음 스크립트의 업데이트 명령문에서 표 1의 두 행은 업데이트 문의 From Clause의 자격을 충족합니다. 그러나 표 1의 행을 사용하여 표 2의 행을 업데이트하는 데 사용되는 행은 정의되지 않았습니다.

USE AdventureWorks;
GO
IF OBJECT_ID ('dbo.Table1', 'U') IS NOT NULL
    DROP TABLE dbo.Table1;
GO
IF OBJECT_ID ('dbo.Table2', 'U') IS NOT NULL
    DROP TABLE dbo.Table2;
GO
CREATE TABLE dbo.Table1 
    (ColA int NOT NULL, ColB decimal(10,3) NOT NULL);
GO
CREATE TABLE dbo.Table2 
    (ColA int PRIMARY KEY NOT NULL, ColB decimal(10,3) NOT NULL);
GO
INSERT INTO dbo.Table1 VALUES(1, 10.0), (1, 20.0), (1, 0.0);
GO

UPDATE dbo.Table2 
SET dbo.Table2.ColB = dbo.Table2.ColB + dbo.Table1.ColB
FROM dbo.Table2 
    INNER JOIN dbo.Table1 
    ON (dbo.Table2.ColA = dbo.Table1.ColA);
GO
SELECT ColA, ColB 
FROM dbo.Table2;

다른 팁

가장 쉬운 방법은 업데이트를 두 가지로 분할하는 것입니다.

UPDATE Customers
SET FirstName = Strings.String
FROM Customers
INNER JOIN Strings ON Customers.ID=Strings.ID AND Strings.Type = 1

그리고:

UPDATE Customers
SET LastName = Strings.String
FROM Customers
INNER JOIN Strings ON Customers.ID=Strings.ID AND Strings.Type = 2

파생 테이블과 같은 한 쿼리에 수행하는 방법이있을 수 있지만, 특정 요구 사항이 아니라면이 접근법을 사용합니다.

Astander는 정확합니다 (나는 그의 대답을 받아들이고 있습니다). 업데이트는 부드러운 커밋되지 않은 문제로 인해 발생하지 않고 조인에 의해 반환 된 여러 행으로 인해 발생합니다. 나는 이것을 확인했다. 업데이트는 여러 레코드에서 생성 된 첫 번째 행 만 선택하여 원본 테이블을 업데이트합니다. 이것은 MSSQL, Sybase 및 그러한 RDMBMS의 동작이지만 Oracle은 이러한 종류의 업데이트를 허용하지 않습니다. MSSQL에 대해 이것을 확인했습니다.

그리고 다시 MSSQL은 커밋되지 않은 데이터로 셀 업데이트를 지원하지 않습니다. 다른 RDBMS와의 상태를 모릅니다. 그리고 anyrdbms가 쿼리 격리 수준 관리에서 제공하는지 전혀 모릅니다.

대체 솔루션은 두 단계로이를 수행하는 것입니다. 이것은 위의 답변에 주어진 방법에 비해 스캔이 적습니다.

INSERT INTO Customers
SELECT 
    ID
    ,MAX(CASE WHEN Type = 1 THEN String ELSE NULL END) AS FirstName
    ,MAX(CASE WHEN Type = 2 THEN String ELSE NULL END) AS LastName
FROM Strings
GROUP BY ID 

저를 도와 주신 친구 로지 토마스에게 감사드립니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top