2

So I was requested to make a few things.... (it is Monday morning and for some reason this whole thing is turning out to be really hard for me to explain so I am just going to try and post a lot of my code; sorry) Oh - the table idea has to stay. Anything else can be changed but the idea of this table and the parsed field was not my idea but it is my responsibility to execute and make work.

Edit: Sorry the post is long. I do suggest a few possible solutions throughout but my problem is ultimately how everything is returned in a dynamically defined table/table variable from something (sp,view,function,anything...). Please take a minute to read the whole post...

First, I needed a table:

CREATE TABLE TICKET_INFORMATION ( 
    TICKET_INFO_ID INT IDENTITY(1,1) NOT NULL, 
    TICKET_TYPE INT, 
    TARGET_ID INT, 
    TARGET_NAME VARCHAR(100), 
    INFORMATION VARCHAR(MAX),   
    TIME_STAMP DATETIME DEFAULT GETUTCDATE()
)

-- insert this row for testing...  
INSERT INTO TICKET_INFORMATION (TICKET_TYPE, TARGET_ID, TARGET_NAME, INFORMATION) VALUES (1,1,'RT_ID','IF_ID,int=1&IF_ID,int=2&OTHER,varchar(10)=val,ue3&OTHER,varchar(10)=val,ue4')

The Information column holds data that needs to be parsed into a table. This is where I am having problems. In the resulting table, Target_Name needs to become a column that holds Target_ID as a value for each row in the resulting table.

The string that needs to be parsed is in this format: @var_name1,@var_datatype1=@var_value1&@var_name2,@var_datatype2=@var_value2&@var_name3,@var_datatype3=@var_value3

And what I ultimately need as a result (in a table or table variable):

RT_ID       IF_ID       OTHER
1           1           val,ue3
1           2           val,ue3
1           1           val,ue4
1           2           val,ue4

And I need to be able to join on the result. Initially, I was just going to make this a function that returns a table variable but for some reason I can't figure out how to get it into an actual table variable. Whatever parses the string needs to be able to be used directly in queries so I don't think a stored procedure is really the right thing to be using.

This is the code that parses the Information string... it returns in a temporary table. In the end, this needs to be passed either just the information string or an ID number or something... doesn't matter what. Or somehow it can be in a view with the ticket_information table.

-- create/empty temp table for var_name, var_type and var_value fields 
if OBJECT_ID('tempdb..#temp') is not null drop table #temp
create table #temp (row int identity(1,1), var_name varchar(max), var_type varchar(30), var_value varchar(max)) 

-- just setting stuff up
declare @target_name varchar(max), @target_id varchar(max), @info varchar(max)
    set @target_name = (select target_name from ticket_information where ticket_info_id = 1) 
    set @target_id = (select target_id from ticket_information where ticket_info_id = 1) 
    set @info = (select information from ticket_information where ticket_info_id = 1) 
    --print @info

-- some of these variables are re-used later    
declare @col_type varchar(20), @query varchar(max), @select as varchar(max) 
set @query = 'select ' + @target_id + ' as ' + @target_name + ' into #target; '
set @select = 'select * into ##global_temp from #target'  


declare @var_name varchar(100), @var_type varchar(100), @var_value varchar(100) 
declare @comma_pos int, @equal_pos int, @amp_pos int        
    set @comma_pos = 1
    set @equal_pos = 1
    set @amp_pos   = 0 

-- while loop to parse the string into a table 
while @amp_pos < len(@info) begin  

    -- get new comma position
    set @comma_pos  = charindex(',',@info,@amp_pos+1)   

    -- get new equal position
    set @equal_pos  = charindex('=',@info,@amp_pos+1)   

    -- set stuff that is going into the table 
    set @var_name   = substring(@info,@amp_pos+1,@comma_pos-@amp_pos-1)  
    set @var_type   = substring(@info,@comma_pos+1,@equal_pos-@comma_pos-1) 

    -- get new ampersand position 
    set @amp_pos    = charindex('&',@info,@amp_pos+1) 
    if @amp_pos=0   or @amp_pos<@equal_pos set @amp_pos = len(@info)+1

    -- set last variable for insert into table 
    set @var_value  = substring(@info,@equal_pos+1,@amp_pos-@equal_pos-1)

    -- put stuff into the temp table 
    insert into #temp (var_name, var_type, var_value) values (@var_name, @var_type, @var_value) 

    -- is this a new field?
    if ((select count(*) from #temp where var_name = (@var_name)) = 1) begin 
        set @query = @query + ' create table #' + @var_name + '_temp (' + @var_name + ' ' + @var_type + '); '    
        set @select = @select + ', #' + @var_name + '_temp '
    end 

    set @query = @query + ' insert into #' + @var_name + '_temp values (''' + @var_value + '''); '   
end 


if OBJECT_ID('tempdb..##global_temp') is not null drop table ##global_temp
exec (@query + @select) 

--select @query
--select @select 

select * from ##global_temp 

Okay. So, the result I want and need is now in ##global_temp. How do I put all of that into something that can be returned from a function (or something)? Or can I get something more useful returned from the exec statement? In the end, the results of the parsed string need to be in a table that can be joined on and used... Ideally this would have been a view but I guess it can't with all the processing that needs to be done on that information string.

Ideas?

Thanks!

Edit: Still looking for answers to this. I would love to have a function that returns a table variable but I don't know how to get the results into a table variable. The result is currently in a global temporary table. Would it work if I defined my table variable in the dynamic portion of the code and then it would just magically be there to return? Or can I somehow select into a table variable from my global temp table, without first defining the columns of the table variable? Or can I create the table variable when I execute the dynamic part? The whole problem is because the columns of the end result are dynamic....... so..... I'm not sure how I could clarify the issues I'm having more. If a function that returns a table is a good route to go - could someone please provide me with code or a link as an example for returning a table variable with a dynamic column definition from a function? Plz, thnx.

4

2 回答 2

2

您可以使用表值函数。这将允许您将结果作为要加入的表返回,就像您要求的那样。

CREATE FUNCTION dbo.GET_TICKET_INFORMATION (... some parameters... )
RETURNS @TICKET_INFORMATION TABLE 
( 
TICKET_INFO_ID INT IDENTITY(1,1) NOT NULL, 
TICKET_TYPE INT, 
TARGET_ID INT, 
TARGET_NAME VARCHAR(100), 
INFORMATION VARCHAR(MAX),   
TIME_STAMP DATETIME DEFAULT GETUTCDATE()
)
 AS 
...
于 2012-09-24T17:27:17.947 回答
1

我使用存储过程返回具有动态列定义的表

我为全局表生成了动态名称:

declare @sp varchar(3)
set @sp = cast( @@spid as varchar(3) )

if object_id ( N'tempdb.dbo.#Periods' ) is not null
    drop table #Periods      
if object_id ( N'tempdb.dbo.##Result' + @sp ) is not null
    execute ( 'drop table ##Result' + @sp )

我有返回周期表的 sp:

create table #Periods
(
    [PERIOD_NUM]    int
    ,[START_DATE]   datetime
    ,[END_DATE]     datetime   
)

insert into #Periods
exec GET_PERIODS_TABLE_SP @pFromDate, @pToDate, @pPeriodType, 0

结果表中的某些字段是动态的:

select @PeriodCount = ...

declare @PeriodsScript varchar(max)  

set @PeriodsScript = ''
set @i = 1

while @i <= @PeriodCount
begin
    set @PeriodsScript = @PeriodsScript + ',PERIOD' + cast (@i as varchar(3))

    set @i = @i + 1
end

生成数据并将其插入##Result:

declare @script varchar(max)

set @script = 'create table ##Result' + @sp +
            '(ROW_NUM int'+
            ',BRANCH_ID int' +
            ',PARAM_NAME varchar(25)' +
            @PeriodsScript + ')'       

execute ( @script )

execute(
            'insert into ##Result' + @sp + '( ROW_NUM, BRANCH_ID, NOM_SIZE_ID, PARAM_NAME )' +
            'select ( row_number() over( order by BRANCH_ID, NOM_SIZE_ID ) - 1 ) * 3 + 1' +
            '        ,BRANCH_ID' +
            '        ,NOM_SIZE_ID' +
            '        ,''Min.price''' +
            '  from ( ' +
            '        select distinct BRANCH_ID' +
            '                ,NOM_SIZE_ID' +
            '          from ##ResultNomSizePrices' + @sp +
            '        ) as t'
            )

最后,从结果表中选择:

set @script = 
            'select distinct gb.TINY_NAME'+
            '        ,r.GROUP_NAME_1 as group1'+
            '        ,r.GROUP_NAME_2 as group2'+
            '        ,r.GROUP_NAME_3 as group3'+
            '        ,r.PARAM_NAME'+
            '        ,r.ROW_NUM'+
            @PeriodsScript +
            '  from ##Result' + @sp + ' as r'+
            ' inner join dbo.GD_BRANCHES as gb'+
            '    on r.BRANCH_ID = gb.BRANCH_ID'+
            ' order by gb.TINY_NAME'+
            '        ,r.GROUP_NAME_1'+
            '        ,r.GROUP_NAME_2'+
            '        ,r.GROUP_NAME_3'+
            '        ,r.ROW_NUM'

 execute ( @script )

ps 对不起我的英语

于 2012-09-25T07:18:43.373 回答