Evaluate in T-SQL

后端 未结 11 2194
悲&欢浪女
悲&欢浪女 2020-12-17 23:42

I\'ve got a stored procedure that allows an IN parameter specify what database to use. I then use a pre-decided table in that database for a query. The problem I\'m having i

相关标签:
11条回答
  • 2020-12-18 00:10
    if exists (select * from master..sysservers where srvname = 'fromdb')
        exec sp_dropserver 'fromdb'
    go
    
    declare @mydb nvarchar(99);
    set @mydb='mydatabase'; -- variable to select database
    
    exec sp_addlinkedserver @server = N'fromdb',
        @srvproduct = N'',
        @provider = N'SQLOLEDB', 
        @datasrc = @@servername,
        @catalog = @mydb
    go
    
    select * from OPENQUERY(fromdb, 'select * from table1') 
    go 
    
    0 讨论(0)
  • 2020-12-18 00:12

    There are a few options, but they are messier than the way you are already doing. I suggest you either:
    (1) Stick with the current approach
    (2) Go ahead and embed the SQL in the code since you are doing it anyway.
    (3) Be extra careful to validate your input to avoid SQL Injection.

    Also, messiness isn't the only problem with dynamic SQL. Remember the following:
    (1) Dynamic SQL thwarts the server's ability to create a reusable execution plan.
    (2) The ExecuteSQL command breaks the ownership chain. That means the code will run in the context of the user who calls the stored procedure NOT the owner of the procedure. This might force you to open security on whatever table the statement is running against and create other security issues.

    0 讨论(0)
  • 2020-12-18 00:14

    Read this... The Curse and Blessings of Dynamic SQL, help me a lot understanding how to solve this type of problems.

    0 讨论(0)
  • 2020-12-18 00:17

    try the sp_executesql built in function. You can basically build up your SQL string in your proc, then call

    exec sp_executesql @SQLString.
    
    DECLARE @SQLString nvarchar(max)
    SELECT @SQLString = '
    SELECT *
    FROM  ' +  @TableName 
    
    EXEC sp_executesql @SQLString
    
    0 讨论(0)
  • 2020-12-18 00:20

    I think Mark Brittingham has the right idea (here: http://stackoverflow.com/questions/688425/evaluate-in-t-sql/718223#718223), which is to issue a use database command and write the sp to NOT fully qualify the table name. As he notes, this will act on tables in the login's current database.

    Let me add a few possible elaborations:

    From a comment by the OP, I gather the database is changed once a month, when it gets "too large". ("We have to load data into a new database each month or else it gets too large. – d03boy")

    1. User logins have a default database, set with sp_defaultdb (deprecated) or ALTER LOGIN. If each month you move on to the new database, and don't need to run the sp on the older copies, just change the login's default db monthly, and again, don't fully qualify the table name.

    2. The database to use can be set in the client login: sqlcmd -U login_id -P password -d db_name, then exec the sp from there.

    3. You can establish a connection to the database using the client of your choice (command line, ODBC, JDBC), then issue a use database command, the exec the sp.

      use database bar; exec sp_foo;

    Once the database has been set using one of the above, you have three choices for executing the stored procedure:

    1. You could just copy the sp along with the database, in to the new database. As long as the table name is NOT fully qualified, you'll operate on the new database's table.

      exec sp_foo;

    2. You could install the single canonical copy of the sp in its own database, call it procs, with the tablename not fully qualified, and then call its fuly qualified name:

      exec procs.dbo.sp_foo;

    3. You could, in each individual database, install a stub sp_foo that execs the fully qualified name of the real sp, and then exec sp_foo without qualifying it. The stub will be called, and it will call the real procedure in procs. (Unfortunately, use database dbname cannot be executed from within an sp.)

      --sp_foo stub:
      create proc bar.dbo.sp_foo 
       @parm int
      as
      begin
        exec procs.dbo.sp_foo @parm;
      end
      go

    However this is done, if the database is being changed, the real sp should be created with the WITH RECOMPILE option, otherwise it'll cache an execution plan for the wrong table. The stub of course doesn't need this.

    0 讨论(0)
提交回复
热议问题