sql >> データベース >  >> RDS >> Oracle

USER_SOURCEoracleのLINEのようなSQLサーバーの行番号

    私は実際にこれを頻繁に行っていたので、掘り下げて、この目的のためだけに何年も前に書いたこの関数を見つけました:

    CREATE function [dbo].[fnSplit3]( 
                    @parameter varchar(Max)                -- the string to split
                    , @Seperator Varchar(64)        -- the string to use as a seperator
            ) 
            RETURNS @Items TABLE(
                    ID INT                                                -- the element number
                    , item VARCHAR(8000)                -- the split-out string element
                    , OffSet int                                -- the original offest
                    --( not entirley accurate if LEN(@Seperator) > 1 because of the Replace() )
            ) 
    AS
    BEGIN 
    /*
    "Monster" Split in SQL Server 2005; From Jeff Moden, 2008/05/22
    
    BYoung, 2008/06/18: Modified to be a Table-Valued Function
                        And to handle CL/LF or LF-only line breaks
      (Note: making it inline made it slower, not faster)
    
    Test: (scripts all triggers in your database)
    
            Select Lines.Item
             From sys.sql_modules M
              Join sys.objects O on O.object_id = M.object_id
              cross apply dbo.fnSplit1(M.definition, char(13)+char(10)) Lines
             Where O.Type = 'TR' 
             Order by O.create_date, Lines.ID
    */
    Declare @Sep char(1)
    Set @Sep = char(10)        --our seperator character (convenient, doesn't affect performance)
    --NOTE: we make the @Sep character LF so that we will automatically
    -- parse out rogue LF-only line breaks.
    
    --===== Add start and end seprators to the Parameter so we can handle
            -- all the elements the same way
            --  Also change the seperator expressions to our seperator
            -- character to keep all offsets = 1
    SET @Parameter = @Sep+ Replace(@Parameter,@Seperator,@Sep) [email protected]
    -- This reduces run-time about 10%
    
    ;WITH cteTally AS
    (--==== Create a Tally CTE from 1 to whatever the length
            -- of the parameter is
     SELECT TOP (LEN(@Parameter))
            ROW_NUMBER() OVER (ORDER BY t1.ID) AS N
      FROM Master.sys.sysColumns t1
       CROSS JOIN Master.sys.sysColumns t2
    )
    INSERT into @Items
            SELECT ROW_NUMBER() OVER (ORDER BY N) AS Number,
                    SUBSTRING(@Parameter, N+1, CHARINDEX(@Sep, @Parameter, N+1)-N-1) AS Value
                    , N+1
             FROM cteTally
             WHERE N < LEN(@Parameter)
              AND SUBSTRING(@Parameter, N, 1) = @Sep --Notice how we find the seperator
    
            Return 
    END
    

    現在、より高速なバージョンがありますが、これは、ここに表示される分割関数の約90%よりも高速です。コメントでテスト例を確認すると、ほぼ正確にあなたが求めていたものです。

            Select O.name, Lines.Item, Lines.ID As LineNo
             From sys.sql_modules M
              Join sys.objects O on O.object_id = M.object_id
              cross apply dbo.fnSplit1(M.definition, char(13)+char(10)) Lines
             Where O.Type = 'P' 
               And Lines.Item LIKE '%SEARCH_STRING%'
             Order by O.name, Lines.ID
    



    1. データベースの速度を大幅に低下させている6つの問題クエリ

    2. mysqlをmysqliに変換しますか?

    3. SQL:フルネームフィールドから名、ミドルネーム、ラストネームを解析します

    4. Oracle 10g:MIN/MAX列値の見積もり