0

EDIT: Some of those who would offer help are unclear about the nature of the requirement, so I will try to state it as clearly as I can:

We need to instantiate a view of an underlying table, and this view must be able to be joined to another table; the difficulty is that the identity of the underlying table is not known until runtime of the ad hoc query doing the join. We would like to do something like this:

  select * from foo
   inner join dynamicallyInstantiatedTable(condition) DT
   on foo.zipcode = DT.zipcode

It doesn't seem possible to create a function that returns TABLE if the function uses dynamic SQL. This is not valid:

   declare @tablename varchar(50);
   -- <snip> code to determine the name of @tablename

   declare @statement varchar(1000);
   set @statement = 'select * from ' + @tablename;
   exec( @statement);

The error:

Invalid use of a side-effecting operator 'EXECUTE STRING' within a function.

If the table name is not known beforehand for whatever reason (e.g. tables are constantly being added and we must select against the most recent one, say), is it possible to do the select dynamically and return a table, either in a stored proc or function?

7
  • Can the SP return the table so that it could be treated as a table, that is, the stored proc name acts as a tablename in another select statement? select * from myproc inner join T.... Commented Oct 9, 2017 at 19:00
  • SELECT * FROM @tablename Commented Oct 9, 2017 at 19:01
  • @Tim Ah, I see what you're asking. Unfortunately, no, you can't do that in either a stored procedure, view, or function. The closest you can get is a procedure that returns a resultset, but you can't treat it as a table. Commented Oct 9, 2017 at 19:01
  • Some really ugly way SELECT * FROM OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters') combined with dynamic SQL may work, But still I wouldn't go that way Commented Oct 9, 2017 at 19:04
  • 1
    tables are constantly being added and we must select against the most recent one It indicates table per date, which is IMHO poor design. And it is antipattern SELECT * FROM sales + @yymm Commented Oct 9, 2017 at 19:07

4 Answers 4

2

Here we go.

I don't use synonyms often, but CREATE SYNONYM supports dynamic SQL.

declare @tablename nvarchar(128);
-- <some code to set @tablename>

declare @sql nvarchar(500);

if object_id(N'dbo.TodaysData', N'SN') is not null
    drop synonym dbo.TodaysData;

set @sql = 
    'create synonym dbo.TodaysData
     for ' + @tablename;

execute(@sql);

select top 5 
    *
from 
    dbo.TodaysData as t
    join
    dbo.SomeOtherTable as s
        on 
           s.FieldName = t.HeresHopingYourSchemaDoesntChange
Sign up to request clarification or add additional context in comments.

1 Comment

Very creative! I like the dynamic use of the synonym.
0

Dynamic SQL in function. No.

is it possible to do the select dynamically and return a table, either in a stored proc or function?

Perhaps I'm missing something (would not be a first) but this seems simple as a stored proc:

The Proc

create proc dbo.getRowsFrom @tablename varchar(50) as
exec('select * from ' + @tablename);

Use

exec dbo.getRowsFrom '<my table>';

Is that what you're looking for?

2 Comments

I need to join <my table> to another.
Ah - ok. Makes sense. Stored proc is out too then. The OPENQUERY solution that lad2025 posted may be the way to go.
0

you should once explain your requirement with example.It is not clear to anybody.

I think everything thing can be done within single proc,no need of another proc or UDF.

declare @tblname varchar(500)
select  @tblname=name from sys.objects
where type_desc ='USER_TABLE'
order by create_date DESC

declare @Sql varchar(max)=''
set @Sql='select * into #tmp from '+@tblname+'  '

set @Sql=@Sql+' select *  from #tmp   drop table #tmp'
exec (@Sql)

Comments

0

Little detail given about your 'join' situation, but it might be easier to jump to your final joined results, rather than focusing on the input table in isolation.

Here I am joining my input table 'a' to a lookup table 'ref', and outputting joined results. If tomorrow your have another input table 'b' - this proc will join that to the lookup table instead. The only requirement is that the join column is consistent.

  declare 
  @inputTableName nvarchar(128)
  ,@sqlExec nvarchar(max)

  set @inputTableName = 'b';

  if(not exists (select 1 from INFORMATION_SCHEMA.TABLES where table_schema = 'test' and TABLE_NAME = 'myView'))
  begin
        select @sqlExec = 'create view test.myView as 
                            select I.*,R.[text] from test.[' + @inputTableName + '] I inner join test.ref  R on I.col0 = R.col0'
end else begin
        select @sqlExec = 'alter view test.myView as 
                            select I.*,R.[text] from test.[' + @inputTableName + '] I inner join test.ref  R on I.col0 = R.col0'
end
    exec (@sqlExec)

select * from test.myView

1 Comment

Thanks for this suggestion, Simon. I have to run but will check later and circle back.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.