2012-03-02 3 views
17

Questo sembra relativamente semplice, ma a quanto pare non lo è.TSQL selezionare nella tabella Temp da dynamic sql

Ho bisogno di creare una tabella temporanea in base a una tabella esistente tramite il prescelto nella sintassi:

SELECT * INTO #TEMPTABLE FROM EXISTING_TABLE 

Il problema è, il nome della tabella esistente viene accettato tramite un parametro ...

I possono ottenere i dati della tabella tramite:

execute ('SELECT * FROM ' + @tableName) 

ma come faccio a sposare i due in modo che posso mettere i risultati del eseguire direttamente nella tabella temporanea.

Le colonne per ogni tabella che verrà utilizzata non sono le stesse, quindi creare la tabella temporanea prima che i dati non siano pratici.

Sono aperto a qualsiasi suggerimento tranne l'utilizzo di una tabella temporanea globale.

Aggiornamento:

Questo è completamente ridicolo, ma le mie prenotazioni con la tabella temporanea globale è che si tratta di una piattaforma multi utente si presta a problemi se la tabella sarà indugiare per lunghi periodi di tempo ...

Sooo .. solo per superare questa parte ho iniziato utilizzando il execute per generare una tabella temporanea globale.

execute('select * into ##globalDynamicFormTable from ' + @tsFormTable) 

Ho quindi utilizzare la tabella temporanea globale per caricare la tabella temporanea locale:

select * into #tempTable from ##globalDynamicFormTable 

Ho quindi eliminare la tabella globale.

drop table ##globalDynamicFormTable 

questo è sporca e non mi piace, ma per il momento, fino a ottenere una soluzione migliore, la sua intenzione di lavorare.

Nel fine:

Credo che non v'è alcun modo per aggirare l'ostacolo.

La risposta migliore sembra essere o;

Creare un visualizzare nel comando execute e utilizzarlo per caricare la tabella temporanea locale nella stored procedure.

Creare una tabella di temperatura globale nel comando execute e utilizzarlo per caricare la tabella di temp locale.

Con ciò detto probabilmente starò semplicemente con la tabella temporanea globale perché la creazione e l'eliminazione di viste viene verificata nella mia organizzazione, e sono sicuro che si metteranno in dubbio che se tutto questo succederà.

Grazie!

+0

In quale versione di SQL Server ci si trova? –

+0

sql server 2005 – Patrick

risposta

19

Un esempio di lavoro.

DECLARE @TableName AS VARCHAR(100) 
SELECT @TableName = 'YourTableName' 

EXECUTE ('SELECT * INTO #TEMP FROM ' + @TableName +'; SELECT * FROM #TEMP;') 

Seconda soluzione con tavolo accessibile temporanea

DECLARE @TableName AS VARCHAR(100) 
SELECT @TableName = 'YOUR_TABLE_NAME' 

EXECUTE ('CREATE VIEW vTemp AS 
     SELECT * 
     FROM ' + @TableName) 
SELECT * INTO #TEMP FROM vTemp 

--DROP THE VIEW HERE  
DROP VIEW vTemp 

/*START USING TEMP TABLE 
************************/ 
--EX: 
SELECT * FROM #TEMP 


--DROP YOUR TEMP TABLE HERE 
DROP TABLE #TEMP 
+0

Secondo SELECT in dopo l'INSERT è per mostrare che è possibile interrogare i dati appena inseriti nella tabella #TEMP. – Kaf

+1

ma la creazione della tabella temporanea nell'esecuzione mette completamente fuori portata la tabella temporanea ... prova a fare una selezione dalla tabella temporanea all'esterno del comando execute ... non funzionerà. – Patrick

+0

declare vartablename as varchar (100) select vartablename = 'collateral' execute ('select * in #temp from' + vartablename) select * from #temp results in - Nome oggetto non valido '#temp'. – Patrick

0

Date un'occhiata a OPENROWSET, e fare qualcosa di simile:

SELECT * INTO #TEMPTABLE FROM OPENROWSET('SQLNCLI' 
    , 'Server=(local)\SQL2008;Trusted_Connection=yes;', 
    'SELECT * FROM ' + @tableName) 
+0

ci sono problemi di pemissioni che impediscono il funzionamento del set di righe aperto, per non parlare del fatto che con 3 ambienti diversi, l'id deve assicurarsi che ogni volta che viene distribuita questa soluzione utilizzi la stringa di connessione corretta per openrowset. – Patrick

+2

Questo non funziona - non è possibile passare variabili a OpenRowset – sianabanana

1
declare @sql varchar(100); 

declare @tablename as varchar(100); 

select @tablename = 'your_table_name'; 

create table #tmp 
    (col1 int, col2 int, col3 int); 

set @sql = 'select aa, bb, cc from ' + @tablename; 

insert into #tmp(col1, col2, col3) exec @sql; 

select * from #tmp; 
+0

funziona anche questo? –

+2

no, ha controllato SQL Server 2008 R2 e non funziona *. –

+0

Aveva un errore (occorre parentesi attorno a @sql) e non ha creato la tabella di esempio da cui selezionare, ma l'approccio generale funziona di fatto. Ho corretto questi problemi. – chorbs

0

Come ho fatto con un perno in SQL dinamico (#AccPurch è stato creato prima di questo)

DECLARE @sql AS nvarchar(MAX) 
declare @Month Nvarchar(1000) 

--DROP TABLE #temp 
select distinct YYYYMM into #temp from #AccPurch AS ap 
SELECT @Month = COALESCE(@Month, '') + '[' + CAST(YYYYMM AS VarChar(8)) + '],' FROM #temp 

SELECT @Month= LEFT(@Month,len(@Month)-1) 


SET @sql = N'SELECT UserID, '+ @Month + N' into ##final_Donovan_12345 FROM (
Select ap.AccPurch , 
     ap.YYYYMM , 
     ap.UserID , 
     ap.AccountNumber 
FROM #AccPurch AS ap 
) p 
Pivot (SUM(AccPurch) FOR YYYYMM IN ('[email protected]+ N')) as pvt' 


EXEC sp_executesql @sql 

Select * INTO #final From ##final_Donovan_12345 

DROP TABLE ##final_Donovan_12345 

Select * From #final AS f 
0

I si può pensare ad alcuni modi per selezionare i dati da una tabella il cui nome è stato generato dinamicamente, senza utilizzare tabelle temporanee globali.

Soluzione 1

Costruire la stringa che contiene il nome della tabella di origine, e rendere la vostra intera query dinamica.

Soluzione 2

Questa soluzione, che coinvolge una variabile di tabella, funzionerà, a condizione che si sa ...

  • ... il numero, il nome e il tipo delle colonne. ..
  • ... il nome della colonna di chiave primaria EDIT: (ok, a quanto pare questo non è assolutamente vero, come it can be generated dynamically) ...

nella tabella di origine.

-- Number of rows in your source table 
DECLARE @RowCount INT; 
SELECT @RowCount = SUM(st.row_count) FROM sys.dm_db_partition_stats st WHERE object_name(object_id) = EmployeesWeek_ + CONVERT(VARCHAR(10),WEEK(GETDATE())) AND (index_id < 2); 

-- All columns from your source table 
DECLARE @col1 int; 
DECLARE @col2 varchar(50); 
DECLARE @col3 varchar(5); 
DECLARE @col4 int; 
DECLARE @col5 smalldatetime; 
DECLARE @col6 bit; 

-- This table variable will store the data 
DECLARE @Dump TABLE (
    col1 int, 
    col2 varchar(50), 
    col3 varchar(5), 
    col4 int, 
    col5 smalldatetime, 
    col6 bit 
) 

DECLARE @RowIter INT = 1; 
WHILE @RowIter <= @RowCount 
BEGIN 
    DECLARE @QueryString NVARCHAR(MAX) = CONCAT(N' 
      SELECT 
       @col1 = ID, 
       @col2 = Name, 
       @col3 = NameAbbr, 
       @col4 = UpdatedBy, 
       @col5 = DateUpdated, 
       @col6 = Active 

      FROM (
       SELECT 
        ROW_NUMBER() OVER (ORDER BY PKArea ASC) AS RowNum, 
        * 
       FROM 
        EmployeesWeek_',WEEK(GETDATE()),' 
      ) sq 

      WHERE 
       RowNum = ', @RowIter , ' 
      ; 
     '); 
    EXEC dbo.sp_executesql 
     @QueryString, 
     -- OUTPUT VARIABLE DECLARATION 
     N' 
      @col1 int out, 
      @col2 varchar(50) out, 
      @col3 varchar(5) out, 
      @col4 int out, 
      @col5 smalldatetime out, 
      @col6 bit out 
     ', 
     -- ALL OUTPUT VARIABLES 
     @col1 out, 
     @col2 out, 
     @col3 out, 
     @col4 out, 
     @col5 out, 
     @col6 out 
    ; 

    INSERT INTO @Dump values(@col1, @col2, @col3, @col4, @col5, @col6); 

    SET @RowIter = @RowIter + 1; 

END 

SELECT * FROM @Dump; 

mio intuito dice che questo è potenzialmente lento su grandi insiemi di dati, e non so se si può fare questa query dinamica (che dovrebbe essere possibile tramite una query l'elenco dei nomi di colonna, using dirty hacks to build the string that contains the list of columns, ecc, ma per ora non posso passare più tempo su questo ...), permettendoti di selezionare i dati da una tabella con un numero qualsiasi di colonne; ma ancora una volta, questo è SQL ...