2012-06-11 2 views
0

SQL2005 데이터베이스 파일에 저장해야하는 C# .net의 개체 목록 (여러 텍스트 파일로 작성)이 있습니다. 불행하게도 테이블 값 매개 변수는 SQL2008에서 시작되었으므로 도움이되지 않습니다. MSDN에서 한 가지 방법은 "여러 데이터 값을 구분 된 문자열 또는 XML 문서로 묶은 다음 해당 텍스트 값을 프로 시저 또는 명령문에 전달하는 것"입니다. 그러나 저장 프로 시저에 새로운 것이므로 그 이상의 도움이 필요합니다. 하나의 레코드를 만들고 내 목록을 반복하고 추가하는 저장 프로 시저를 만들 수 있다는 것을 알고 있습니다.하지만 피하려고하는 것입니다. 감사.저장 프로 시저에 여러 행의 데이터 전달

Input file example (Other files contain pricing and availability): 
Matnr ShortDescription LongDescription ManufPartNo Manufacturer ManufacturerGlobalDescr GTIN ProdFamilyID ProdFamily ProdClassID ProdClass ProdSubClassID ProdSubClass ArticleCreationDate CNETavailable CNETid ListPrice Weight Length Width Heigth NoReturn MayRequireAuthorization EndUserInformation FreightPolicyException 
10000000 A&D ENGINEERING SMALL ADULT CUFF FOR UA-767PBT UA-279 A&D ENGINEERING A&D ENG 093764011542 GENERAL General TDINTERNL TD Internal TDINTERNL TD Internal 2012-05-13 12:18:43 N  18.000 .350    N N N N 
10000001 A&D ENGINEERING MEDIUM ADULT CUFF FOR UA-767PBT UA-280 A&D ENGINEERING A&D ENG 093764046070 GENERAL General TDINTERNL TD Internal TDINTERNL TD Internal 2012-05-13 12:18:43 N  18.000 .450    N N N N 

일부 데이터베이스 파일 필드 :

EffectiveDate   varchar(50) 
MfgName     varchar(500) 
MfgPartNbr    varchar(500) 
Cost     varchar(200) 
QtyOnHand    varchar(200) 
+0

[무엇을 시도해 봤습니까?] (http://whathaveyoutried.com)해야 할 일 및 내게 보이는 물체는 무엇입니까? –

+0

내 개체는 데이터베이스의 필드에 해당하는 11 개의 문자열 속성으로 구성됩니다. 지금까지 제가 시도한 유일한 방법은 방향을 찾는 것입니다. –

+0

별도의 레코드로 저장하지 않고 다른 테이블의 관계와 함께 묶지 않는 이유는 무엇입니까? –

답변

2

당신은 아주 쉽게 하나의 문자열에서 여러 값을 분할 할 수 있습니다.

foo, 20120101, 26; bar, 20120612, 32 

(이 콜론과 세미콜론 자연스럽게 나타나지 않을 수 있다고 가정합니다 : 당신이 "열"과 "행"을 구분하는 세미콜론을 구분하는 쉼표를 사용하여,이 같은 문자열을 묶을 수있는 말 가능한 경우 다른 구분 기호를 선택해야합니다.

원본 문자열에 값이 나타나는 순서를 결정할 수있는 출력 열을 포함하여 이와 같은 분할 루틴을 작성할 수 있습니다 :

CREATE FUNCTION dbo.SplitStrings 
(
    @List  NVARCHAR(MAX), 
    @Delimiter NVARCHAR(255) 
) 
RETURNS TABLE 
AS 
    RETURN (SELECT Number = ROW_NUMBER() OVER (ORDER BY Number), 
     Item FROM (SELECT Number, Item = LTRIM(RTRIM(SUBSTRING(@List, Number, 
     CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number))) 
    FROM (SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) 
     FROM sys.all_objects) AS n(Number) 
    WHERE Number <= CONVERT(INT, LEN(@List)) 
     AND SUBSTRING(@Delimiter + @List, Number, 1) = @Delimiter 
    ) AS y); 
GO 

다음과 같이 쿼리 할 수 ​​있습니다 (단순형 성만와 그림 난 단지 3 곳을 취급하고있어하지만 당신은 11 또는 n)에 대해이 작업을 추정 할 수 있습니다

DECLARE @x NVARCHAR(MAX); -- a parameter to your stored procedure 

SET @x = N'foo, 20120101, 26; bar, 20120612, 32'; 

;WITH x AS 
(
    SELECT ID = s.Number, InnerID = y.Number, y.Item 
    -- parameter and "row" delimiter here: 
    FROM dbo.SplitStrings(@x, ';') AS s 
    -- output and "column" delimiter here: 
    CROSS APPLY dbo.SplitStrings(s.Item, ',') AS y 
) 
SELECT 
    prop1 = x.Item, 
    prop2 = x2.Item, 
    prop3 = x3.Item 
FROM x 
INNER JOIN x AS x2 
ON x.InnerID = x2.InnerID - 1 
AND x.ID = x2.ID 
INNER JOIN x AS x3 
ON x2.InnerID = x3.InnerID - 1 
AND x2.ID = x3.ID 
WHERE x.InnerID = 1 
ORDER BY x.ID; 

결과 :

prop1 prop2  prop3 
------ -------- ------- 
foo  20120101 26 
bar  20120612 32 
+0

이것은 데이터 크기와 내용에 따라 유용 할 수 있으며 완전히 개발되고 테스트 된 대답은 +1입니다. 그러나 여기에 구현에 대한 몇 가지주의 사항과 대체 전략에 대한 나의 대답을보십시오. 특히, T-SQL 스플릿 UDF는 느려질 수 있으며 여기에 표시된 'dbo.SplitStrings'UDF는 더 복잡한 데이터 (예 : 값에 구분 기호가 포함될 수있는 위치)에 적합하지 않습니다. 하지만주의해야 할 점은 문제를 적게 만들기 위해 항상 구분자를 덜 선택할 수 있다는 것입니다. –

+0

@DominicP 구분 기호를 현명하게 선택하는 것에 대한 답변에서 면책 조항을 만들었습니다. –

+0

맞습니다. 나는 더 분명해야했습니다. 제가 말한 것은 단지 데이터가 제약이없는 구분자 인 경우 실제로 좀 더주의를 끌기를 바라는 다소 까다로운 문제가 될 수 있다는 이론적 인 점이었습니다. 실제로 입력 데이터에 대해 합리적인 가정을 할 수 있기 때문에 분할 기능을 실현할 수 있습니다. 따라서 나는 대답을 지었다. 오해를해서 죄송합니다. –

0

우리는이 같은 XML 데이터 유형을 사용하여 ...

여기

declare @contentXML xml 
set @contentXML=convert(xml,N'<ROOT><V a="124694"/><V a="124699"/><V a="124701"/></ROOT>') 

SELECT content_id, 
    FROM dbo.table c WITH (nolock) 
    JOIN @contentXML.nodes('/ROOT/V') AS R (v) ON c.content_id = R.v.value('@a', 'INT') 
은 ... 저장 프로 시저를 호출하는 경우처럼 보일 것 인 것이다

DbCommand dbCommand = database.GetStoredProcCommand("MyStroredProcedure); 
database.AddInParameter(dbCommand, "dataPubXML", DbType.Xml, dataPublicationXml); 

CREATE PROC dbo.usp_get_object_content 
(
    @contentXML XML 
) 
AS 
BEGIN 
    SET NOCOUNT ON 

    SELECT content_id, 
     FROM dbo.tblIVContent c WITH (nolock) 
     JOIN @contentXML.nodes('/ROOT/V') AS R (v) ON c.content_id = R.v.value('@a', 'INT') 

END 

SQL Server는 XML을 매우 빠르게 구문 분석하지 않으므로 SplitStrings 함수를 사용하면 성능이 향상 될 수 있습니다. 그냥 대안을 제공하고 싶었습니다.

0

몇 가지 옵션을 생각해 볼 수는 있지만, 그 중 하나 (분할 옵션)를 입력 할 때 위의 Mr.Bertrand가 게시했습니다. 유일한 문제는 SQL just isn't that good at string manipulation입니다.

그래서 다른 옵션은 sproc이 가정 할 #Temp 테이블을 사용하는 것입니다. 다음과 같은 효과를 동적 SQL을 구축 :

INSERT INTO #InsertData SELECT <values> UNION ALL SELECT <values>....

는,이 방법에의 한 몇 가지 제한 사항이 있습니다 사용하여 트랜잭션, 당신이 필요로하는 모양, 삽입하고자하는 데이터에 다음 루프 CREATE TABLE #InsertData을 시작

즉, 데이터 세트가 매우 커질수록 INSERT를 일괄 처리로 분할해야 할 수도 있습니다. (나는이 실수를 배웠을 때의 특정 오류를 기억하지 않지만, SQL의 매우 긴 목록에 대해서는 SQL 불평이있다.) 솔루션은 간단하다. 단지 작은 수의 INSERT를 생성하면된다. 각 행. 예를 들어, 1 INSERT SELECT과 10000 UNION ALLs 대신 각각 인 INSERT SELECTs을 수행 할 수 있습니다.한 번에 전체 배치를 하나의 명령의 일부로 전달할 수 있습니다.

임시 테이블, 긴 명령 문자열 등 다양한 단점에도 불구하고이 장점은 모든 문자열 처리를 훨씬 효율적인 C# 측면의 방정식으로 오프로드하므로 추가 영구 데이터베이스 객체 (분할 함수; 가끔은 이들 중 하나가 필요하지 않음)?

Split() 함수를 사용하는 경우 위의 링크에서 설명한 성능상의 이유로 T-SQL UDF가 아닌 SQLCLR 함수에서이 함수를 오프로드하는 것이 좋습니다. 마지막으로

, 당신이 무엇을 데이터 인 경우 데이터가 (구분 기호를 포함 예를 들어, 아론의 대답에 당신이 문제에 실행 문자열을 포함 할 경우 더 많은 문제를 가지고 있습니다주의, 선택 방법 :

'I pity the foo!', 20120101, 26; 'bar, I say, bar!', 20120612, 32 
C 번호는 T-SQL에 비해 문자열 처리에서 더 나은 때문에

다시 말하지만, 당신은이 문제를 처리하기 위해 T-SQL UDF를 사용하지 않고 더 나을 수 있습니다.

편집

주의 사항 다음은 동적 인 INSERT 옵션에 대해 생각해 볼 수있는 기타 포인트.

입력 사항이 잠재적으로 위험한 입력인지 여부를 결정해야하며 사용하기 전에 청소해야합니다. 이 데이터를 쉽게 매개 변수화 할 수 없으므로 이것은 중요한 데이터입니다. 이 전략을 사용했던 곳에서는 데이터 유형에 대해 이미 강력한 보장을했습니다 (특히 정수 ID 목록이있는 테이블을 처리 할 때 사용했기 때문에 정수가 아닌 임의적으로 반복했습니다. 신뢰할 수없는 문자열). 유사한 보증이 없다면 SQL 인젝션의 위험성을 인식하십시오.

관련 문제