如何循环遍历 sql 语句中的存储过程

Posted

技术标签:

【中文标题】如何循环遍历 sql 语句中的存储过程【英文标题】:How do I loop through a stored procedure within a sql statement 【发布时间】:2016-07-19 11:38:42 【问题描述】:

我知道这听起来像是一个老问题,但即使阅读了无数的答案,我也无法解决我的问题,所以我会尽量具体。 我有一个包含一列文本的表格,其中有时包含 html 标记。我需要删除大部分 HTML 但留下一些。我编写了以下代码:

      DECLARE @Start INT = 1;
  DECLARE @End INT = 1;
  DECLARE @Length INT = 0;
  DECLARE @Keep INT = 0;
  DECLARE @ReplaceChar VARCHAR(10) = '';
  DECLARE @Offset INT = 0;
  RETURN;

  WHILE @Start > 0 AND @End > 0
    BEGIN
      SET @ReplaceChar = (SELECT CASE WHEN SUBSTRING(@HTMLText,@Start + 1, 7) IN ('/strike')
                                      THEN ('</strike>')
                                      WHEN SUBSTRING(@HTMLText,@Start + 1, 6) IN ('strike')
                                      THEN ('<strike>')
                                      WHEN SUBSTRING(@HTMLText,@Start + 1, 4) IN ('br /')
                                      THEN ('<br />')
                                      WHEN SUBSTRING(@HTMLText,@Start + 1, 3) IN ('/th', '/tr','/td','th ')
                                      THEN ('<' + SUBSTRING(@HTMLText,@Start + 1, 3) + '>')
                                      WHEN SUBSTRING(@HTMLText,@Start + 1, 2) IN ('th', 'tr', 'td')
                                      THEN ('<' + SUBSTRING(@HTMLText,@Start + 1, 2) + '>')
                                      WHEN SUBSTRING(@HTMLText,@Start + 1, 2) IN ('/p', '/i', '/b')
                                      THEN ('<' + SUBSTRING(@HTMLText,@Start + 1, 2) + '>')
                                      WHEN SUBSTRING(@HTMLText,@Start + 1, 1) IN ('p', 'i', 'b')
                                      THEN ('<' + SUBSTRING(@HTMLText,@Start + 1, 1) + '>')
                                      ELSE ''
                                 END);
      SET @Keep = (SELECT CASE WHEN SUBSTRING(@HTMLText,@Start + 1, 7) IN ('/strike') THEN 1
                               WHEN SUBSTRING(@HTMLText,@Start + 1, 6) IN ('strike') THEN 1
                               WHEN SUBSTRING(@HTMLText,@Start + 1, 4) IN ('br /') THEN 1
                               WHEN SUBSTRING(@HTMLText,@Start + 1, 3) IN ('/th', '/tr', '/td') THEN 1
                               WHEN SUBSTRING(@HTMLText,@Start + 1, 2) IN ('th', 'tr', 'td') THEN 1
                               WHEN SUBSTRING(@HTMLText,@Start + 1, 2) IN ('/p', '/i', '/b') THEN 1
                               WHEN SUBSTRING(@HTMLText,@Start + 1, 1) IN ('p', 'i', 'b') THEN 1
                               ELSE 0
                          END);

      SET @HTMLText = RTRIM((LTRIM(STUFF(@HTMLText,@Start, @Length,@ReplaceChar))));
      SET @Start = CHARINDEX('<', @HTMLText,@Start + @Offset);
      SET @End = CHARINDEX('>', @HTMLText,CHARINDEX('<', @HTMLText,@Start + @Offset));
      SET @Length = (@End - @Start) + 1; 
      SET @Offset = @Start + @Keep;

    END;

  RETURN @HTMLText;

这需要在替换功能完成后应用于以下代码中的详细信息列。

DECLARE @Region  NVARCHAR(12) = '11'
DECLARE @Location NVARCHAR (1000) = '1932'
DECLARE @IPM NVARCHAR (500) = '1594,1611,1934' -- for 1932 --'8055,15591'--for 1941
DECLARE @NoteFromDate DATETIME = '20150101'
DECLARE @NoteToDate DATETIME= '20160701'
  SELECT r.RegionName
    , l.LocationName
    , CASE WHEN o.CurrentLocationId <> l.LocationId
           THEN '*'
           ELSE ''
      END AS NotCurrentLocation
    , e.DisplayName AS IPM
    , ec.DisplayName AS Counselor
    , oni.OffenderId
    , an.LastName + ', ' + an.FirstName + COALESCE(' ' + an.MiddleName,
                                        '') AS OffenderName
    , oni.NoteDate
    ,REPLACE(REPLACE(REPLACE(REPLACE(
        ono.Details,'''',''),'&nbsp;',' '),'&amp;',' & '),'rsquo;','-')
    FROM ref.Employee AS e
    INNER JOIN ref.Location AS l
      ON e.LocationId = l.LocationId
    INNER JOIN ref.Region AS r
      ON l.RegionId = r.RegionId
    INNER JOIN ind.OffenderNoteInfo AS oni
      ON e.EmployeeId = oni.StaffId
    INNER JOIN ind.Offender AS o
      ON oni.OffenderId = o.OffenderId
    INNER JOIN ind.OffenderNote AS ono
      ON oni.OffenderNoteInfoId = ono.OffenderNoteInfoId
    INNER JOIN ind.OffenderNoteInfo_ContactMode AS onicm
      ON oni.OffenderNoteInfoId = onicm.OffenderNoteInfoId
    INNER JOIN ind.AliasName AS an
      ON oni.OffenderId = an.OffenderId AND an.AliasNameTypeId = 0 --Default Name
    LEFT JOIN ind.OffenderCurrentFactPart AS ocfp
      ON o.OffenderId = ocfp.OffenderId
    LEFT JOIN hsn.CounselorAssignment AS ca
      ON ocfp.PriCounselorAssignmentId = ca.CounselorAssignmentId
    LEFT JOIN ref.Employee AS ec
      ON ca.EmployeeId = ec.EmployeeId
    WHERE e.LocationId IN (
      SELECT Value
        FROM vnfa.udf_FnSplit(@Location, ',')) AND e.EmployeeTypeId = 106 --Treatment Program Supervisor
      AND oni.NoteTypeId = 11 --Facility Notes
      AND onicm.ContactModeId = 229 --Institution Fidelity Review
      AND (oni.NoteDate >= @NoteFromDate AND oni.NoteDate <= @NoteToDate) AND e.EmployeeId IN (
      SELECT Value
        FROM vnfa.udf_FnSplit(@IPM, ',')); 

如何让代码部分 1 在代码部分 2 中运行?

详细信息列的输入可能如下所示:

<p style="margin: 0in 0in 0pt;"><span style="font-family: Calibri;">All areas were reviewed </span></p>

输出应该是:

<p>All areas were reviewed</p>

我只是没有看到将这两者组合到每一行的方法。感谢您的任何建议。

【问题讨论】:

查看光标,光标内可以有光标 可能不是您要查找的内容,但我会使用其他语言提供的服务或代码从源头清理 html。您还可以使用相同的过程一次性清理现有数据 我同意 Mike 的观点,SQL Server 不是这项工作的工具。我会让 SQL 完成这项任务的最接近方法是调用 CLR 函数。我非常喜欢Old Shoe or Glass Bottle? 对这种情况的类比。 【参考方案1】:

我会按照其他人的建议做,并用另一种语言编写这段代码。但是,您可以使用 tsql 来完成。第一个代码可以是一个标量函数,然后可以将其应用于查询中的详细信息列。

【讨论】:

以上是关于如何循环遍历 sql 语句中的存储过程的主要内容,如果未能解决你的问题,请参考以下文章

pl/sql 循环遍历表并将行的每个条目传递给存储过程

利用mysql存储过程循环插入新数据并更新

MySQL存储过程循环遍历变量并插入临时表

oracle存储过程中循环调用存储过程

MySQL---存储过程 及 条件语句循环语句

SQL - 使用 select 语句和循环来填充存储过程