سؤال

لقد فعلت الكثير من عبارات مسار XML ، لكن هذا يهرب مني أو قد لا يكون ممكنًا مع العديد من الأطفال المختلفين.

يجب أن تبدو النتيجة النهائية هكذا

<Process>
<TaskList>
<SqlTask Name="Get Report Parameters">
    <StoredProcName>GetReportParameters</StoredProcName>
        <ConnectionName>Local</ConnectionName>
        <DataTableName>DistributionList</DataTableName>
        <Parameters>
              <Parameter>
            <Name>ReportName</Name>
            <Value>TheReprot</Value>
            <Type>String</Type>
              </Parameter>
        </Parameters>
  </SqlTask>
  <LoopTask Name="Loop Report Creation" ContainerKey="DistributionList">
  <TaskList>
        <ReportTask Name="Report In Loop">   
    </ReportTask>
</TaskList>
  </LoopTask>
  <SqlTask Name="Get Email Addresses">
    <StoredProcName>GetMailingAddress</StoredProcName>
        <ConnectionName>Local</ConnectionName>
        <DataTableName>EmailList</DataTableName>

  </SqlTask>
  <LoopTask Name="Loop Mail Creation" ContainerKey="EmailList">
<TaskList>
        <MailTask Name="Send Email In Loop">       
        </MailTask>
</TaskList>
  </LoopTask>
</TaskList>
</Process>

فيما يلي بعض جدول الاختبار والبيانات التي لدي حتى الآن. السؤال هو في الحقيقة كيف يمكنني عرض عقد الأطفال المختلفة تحت نفس الجذر. وهل يمكنني استنباط اسم علامة من قيمة العمود؟

CREATE TABLE #TASK (
    TaskId INT IDENTITY(1,1)
,    ProcessId INT
,    TaskType VARCHAR(255)
,    TaskName VARCHAR(255)
,    ContainerKey VARCHAR(255)
,    ParentTaskId INT
)

CREATE TABLE #TASK_PARAMETERS 

(
    TaskId INT
,    Name VARCHAR(255)
,    Value VARCHAR(MAX)
,    [Type] VARCHAR(128)
)

CREATE TABLE #TASK_DETAILS
(
    TaskId INT
,    DetailName VARCHAR(255)
,    DetailValue VARCHAR(MAX)
)

DECLARE @TaskId AS INT
DECLARE @ParentTaskId AS INT


INSERT INTO #TASK 
(
    ProcessId
,    TaskType
,    TaskName
,    ContainerKey
,    ParentTaskId
)
VALUES 
(
0
,    'SqlTask'
,    'Get Report Parameters'
,    NULL
,    NULL
)

SET @TaskId = @@IDENTITY

INSERT INTO #TASK_DETAILS
(
    TaskId
,    DetailName
,    DetailValue
)
VALUES 
(
    @TaskId
,    'StoredProceName'
,    'GetReportParamters'
)

INSERT INTO #TASK_DETAILS
(
    TaskId
,    DetailName
,    DetailValue
)
VALUES 
(
    @TaskId
,    'ConnectionName'
,    'Local'
)

INSERT INTO #TASK_DETAILS
(
    TaskId
,    DetailName
,    DetailValue
)
VALUES 
(
    @TaskId
,    'DataTableName'
,    'DistributionList'
)

INSERT INTO #TASK_PARAMETERS 

(
    TaskId
,    Name
,    Value
,    [Type]
)
VALUES 
(
    @TaskId
,    'ReportName'
,    'TheReprot'
,   'String'
)


INSERT INTO #TASK 
(
    ProcessId
,    TaskType
,    TaskName
,    ContainerKey
,    ParentTaskId
)
VALUES 
(
0
,    'LoopTask'
,    'Loop Report Creation'
,    'DistributionList'
,    NULL
)

SET @ParentTaskId = @@IDENTITY


INSERT INTO #TASK 
(
    ProcessId
,    TaskType
,    TaskName
,    ContainerKey
,    ParentTaskId
)
VALUES 
(
0
,    'ReportTask'
,    'Report In Loop'
,    NULL
,    @ParentTaskId
)


INSERT INTO #TASK 
(
    ProcessId
,    TaskType
,    TaskName
,    ContainerKey
,    ParentTaskId
)
VALUES 
(
0
,    'SqlTask'
,    'Get Email Addresses'
,    NULL
,    NULL
)

SET @TaskId = @@IDENTITY

INSERT INTO #TASK_DETAILS
(
    TaskId
,    DetailName
,    DetailValue
)
VALUES 
(
    @TaskId
,    'StoredProceName'
,    'GetMailingAddress'
)

INSERT INTO #TASK_DETAILS
(
    TaskId
,    DetailName
,    DetailValue
)
VALUES 
(
    @TaskId
,    'ConnectionName'
,    'Local'
)

INSERT INTO #TASK_DETAILS
(
    TaskId
,    DetailName
,    DetailValue
)
VALUES 
(
    @TaskId
,    'DataTableName'
,    'EmailList'
)


INSERT INTO #TASK 
(
    ProcessId
,    TaskType
,    TaskName
,    ContainerKey
,    ParentTaskId
)
VALUES 
(
0
,    'LoopTask'
,    'Loop Mail Creation'
,    'EmailList'
,    NULL
)

SET @ParentTaskId = @@IDENTITY

INSERT INTO #TASK 
(
    ProcessId
,    TaskType
,    TaskName
,    ContainerKey
,    ParentTaskId
)
VALUES 
(
0
,    'MailTask'
,    'Send Email In Loop'
,    NULL
,    @ParentTaskId
)


SELECT *
FROM #TASK

SELECT *
FROM #TASK_PARAMETERS 

SELECT *
FROM  #TASK_DETAILS
هل كانت مفيدة؟

المحلول

صحيح ، لديك العديد من المشكلات التي يجب التغلب عليها مع عينة!

أولاً ، سأقدم لك الإجابة ، على الرغم من أنه من أجل معالجة بشكل صحيح بشكل صحيح ، يجب أن تكون وظيفة متكررة ، لذلك كان يجب إنشاء بيانات الاختبار التي قدمتها في جداول دائمة بدلاً من مؤقت (أبسط) وبعد ذلك أنا " أشر إلى بعض التقنيات المفيدة التي استخدمتها في حل المشكلة.

ALTER FUNCTION GetTasks (@ParentId varchar(255)= NULL) 
RETURNS
XML
BEGIN
DECLARE @ReturnXML XML

SELECT @ReturnXML = 
(
    SELECT
    (
        SELECT 
            CONVERT(XML,
                --Main task start tag
                '<'+master_t.TaskType+' Name="'+master_t.TaskName+'">'+ 
                    CONVERT(VARCHAR(MAX),
                        (

                            SELECT
                            dbo.GetTasks(master_t.TaskId),
                            (
                                SELECT 
                                    CONVERT(XML,'<'+DetailName+'>'+DetailValue+'</'+DetailName+'>')
                                FROM
                                    TASK_DETAILS t 
                                WHERE
                                    TaskId = master_t.TaskId
                                FOR XML PATH(''),Type
                            ),
                            (
                                SELECT Name,Value,Type FROM TASK_PARAMETERS t 
                                WHERE TaskId=master_t.TaskId
                                FOR XML PATH('Parameter'),Type
                            ) 'Parameters'
                            FOR XML PATH(''),Type 
                        )
                    )
                    +
                --Main task end tag
                '</'+master_t.TaskType+'>'
            )
        FROM 
            TASK master_t
        WHERE 
            --Effectively ignore the parentId field if it is not passed.
            ISNULL(ParentTaskId,'') = CASE WHEN @ParentId IS NULL THEN '' ELSE @ParentId END


        FOR XML PATH(''),Type
    ) 'TaskList'  FOR XML PATH(''),Type
) 

RETURN @ReturnXML
END
GO

استدعاء هذه الوظيفة مثل هذه:

SELECT dbo.GetTasks(NULL)

صحيح التقنيات التي أعتقد أنها تستحق الإشارة إليها هي:

أ) يمكنك إنشاء عقد XML يدويًا عن طريق ببساطة بنائها من السلاسل- وهذا مفيد إذا كانت أسماء العقدة في الجدول. الشيء الوحيد الذي يجب أن تكون على دراية به هو أن تضع علامة مفتوحة وإغلاق حول كتلة ، فمن المحتمل أن تضطر إلى تحويل الكتلة إلى سلسلة أولاً ، وتصلب على العلامات ، ثم تحويل الأمر بأكمله إلى XML (PetcemeMeal لن تعمل كوظيفة التحويل إلى XML تتوقع منك تقديم XML المشكلة جيدًا.

ب) يجب عليك أحيانًا أن تعشش الأشياء بين قوسين لتحقيق علامة حول جميع الأدوات الفرعية ... مثال يجعل هذا أكثر وضوحًا:

 SELECT 
    TaskName
    FROM TASK t
    FOR XML PATH('SomeRoot')

سوف تنتج:

<SomeRoot>
  <TaskName>Get Report Parameters</TaskName>
</SomeRoot>
<SomeRoot>
  <TaskName>Loop Report Creation</TaskName>
</SomeRoot>
<SomeRoot>
  <TaskName>Report In Loop</TaskName>
</SomeRoot>
<SomeRoot>
  <TaskName>Get Email Addresses</TaskName>
</SomeRoot>
<SomeRoot>
  <TaskName>Loop Mail Creation</TaskName>
</SomeRoot>
<SomeRoot>
  <TaskName>Send Email In Loop</TaskName>
</SomeRoot>

للحصول على "Someroot" لتظهر حوله ، يمكنك القيام بذلك:

SELECT 
(
    SELECT 
        TaskName
    FROM TASK t
    FOR XML PATH(''),Type
) 
FOR XML PATH('SomeRoot')

إذا كان اسم العقدة ثابتًا (لاحظ مسار XML ('')،يكتب, ، وهو ما يضمن أساسًا أن مسار XML يعيد بيانات نوع XML لمزيد من المعالجة ولا يفلت منه)

إذا لم يكن اسم العقدة ثابتًا ، فأنت عالق بشيء من هذا القبيل ، مع الحاجة إلى التحويل إلى السلسلة من وإلى سلسلة لجعلها تعمل.

SELECT 
    CONVERT(XML,
        '<'+DynamicName+'>' + 
        CONVERT(VARCHAR(MAX),
                (
                    SELECT 
                        TaskName
                    FROM TASK t
                    FOR XML PATH(''),Type
                )
            ) +
            '</'+DynamicName+'>'  
    )
FROM
    (SELECT 'Test' as DynamicName) a

ج) فيما يتعلق بسؤالك حول جعل علامات الأطفال المختلفين تظهر على نفس المستوى ، إنه تافهة إلى حد ما ، وعليك فقط أن تتذكر أن المشكلة المعتادة لطبقات متعددة من Select تتوقف عن أن تكون مشكلة في XML كما تحدد XML فقط أ إرجاع أ كائن XML واحد. يمكنك بعد ذلك استخدام مسار XML لدمج هذه النتائج في شجرة أيضًا.

على سبيل المثال

SELECT 
    (SELECT top 1 * FROM TASK FOR XML PATH(''),Type),
    (SELECT top 1 * FROM TASK_DETAILS FOR XML PATH(''),Type)

سيعود صفًا واحدًا مع عمودين ولكن إذا قمت بتطبيق مسار XML ('') على الكل ، فقد قمت بدمجهما على نفس المستوى

SELECT 
    (SELECT top 1 * FROM TASK FOR XML PATH(''),Type),
    (SELECT top 1 * FROM TASK_DETAILS FOR XML PATH(''),Type)
FOR XML PATH('Root')    

د) يتم تحويل أسماء الأعمدة إلى عقد لك إذا كان عن طريق مسار XML. السمات سهلة للغاية من حيث أنك فقط تعطي العمود اسم مستعار وهو مسار XSL المناسب على سبيل المثال mynodename MyAttributeName "من الواضح أن هذا يمنع السمات التي يتم تسميتها أيضًا ديناميكيًا. لذلك ، في هذا المثال ، قمت للتو ببناء XML من الأوتار مرة أخرى. هذا هو السبب في أن أسماء العقدة الديناميكية هي فكرة سيئة- فأنت تسمح بشكل أساسي لروتينك بإنشاء أسماء سمات جديدة وأسماء العقدة عبر البيانات في الجدول ... وهذا يعني أنه لا يمكنك إنشاء مخطط لائق لروتينك AS AS الخاص بك أنت لا تعرف مقدمًا ما هي البيانات التي قد تكون في الجدول ...

الانتقال :)

لذلك ، نظرًا لتلك اللبنات الأساسية ، فإن أسهل شيء يجب القيام به هو العمل من أعمق مستوى ، وبنشته بلوك ، ثم يُمزج كما هو أعلاه.

لقد فعلت ذلك من أجل استعلامك ، وأدركت في النهاية أنه لجعله يعمل بشكل هرمي (أي مستويات متداخلة) كان عليّ أن أكتب هو كدالة تعود إلى XML ، والتي تسمى تمرير الأمومة إليها (بحيث تعرف الوظيفة ماذا تفعل تصفية النتيجة المحددة إلى). سيموت هذا موتًا فظيعًا إذا كان التسلسل الهرمي سيئًا ودائمًا.

حسنًا- نأمل أن يكون هناك شيء ما يمكنك العمل معه. هذا هو حل XML المسار () الموجود - هناك طرق XML بديلة يمكن أن تكون مفيدة في المواقف المختلفة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top