5

In Oracle, you can create a temp table using something like:

CREATE GLOBAL TEMPORARY TABLE temp_table (
    field1 NUMBER,
    field2 NUMBER
)
ON COMMIT DELETE ROWS;

... which could be pretty nifty, as this creates a table visible to everyone, but the data one INSERTs into the table is visible only to him or her. Additionally, that data is automatically deleted on at the end of the transaction or the session (depending on its declaration), leaving everyone else's temporary data unharmed.

In SQL Server, however, you can create a temp table with:

CREATE TABLE #temp_table (field1 INT, field2 INT);

... which, as I understand it, is substantially and functionally different than Oracle's implementation. This temp table is visible only to you, and is dropped (the table) immediately after use.

Is there any capacity in SQL Server to mimic the Oracle behavior as described above? Or is the only way to work with temporary data involve having to repeatedly CREATE the temp table with each iteration of work?

APC
  • 137,061
  • 19
  • 153
  • 266
Richard Neil Ilagan
  • 14,133
  • 5
  • 44
  • 64
  • can you explain why you would want to mimic the Oracle behaviour in SQLServer? Is it just to avoid the requirement to execute the CREATE TABLE statement? –  Sep 10 '10 at 14:50
  • @Mark ~ well, that primarily. But if I was dealing with (1) repetitive temp data inserts, (2) with generally the same data format and fields, (3) and is user-unique (i.e. data is private to a user session), it just makes much more sense to handle all that in a table as per Oracle's implementation. :) – Richard Neil Ilagan Sep 13 '10 at 00:06
  • [Oracle Private Temporary Tables](https://stackoverflow.com/a/48852466/5070879) – Lukasz Szozda Feb 18 '18 at 14:01

3 Answers3

9

As you have discovered SQL Server & Oracle temporary tables are fundamentally different.

In Oracle global temporary tables are permanent objects that store temporary session specific (or transaction specific) data.

In SQL Server temporary tables are temporary objects storing temporary data, with #temp_tables storing data that is local to a session and ##temp_tables storing data that is global. (I have never had a need for SQL Server global temp tables and don't know what problem they solve.) If the #temp_table was created in a stored procedure it will be dropped when the stored procedure exits. Otherwise it will be dropped when the session closes.

And no, there really isn't a way to make SQL Server mimic Oracle. You could use a normal table with an extra column storing a session ID. But you wouldn't get the advantages of temp tables with respect to less logging. You'd have to manually delete the temp data. And deal with cleaning up from sessions that quit prematurely.

EDIT: Another difference between Oracle and SQL Server is that SQL Server allows DDL to be wrapped in a transaction with other statements. So if you need to use a temp table as part of a larger transaction, the create table #table_name... statement will not implicitly commit the current transaction like a create table statement would in Oracle.

Shannon Severance
  • 16,477
  • 3
  • 40
  • 63
  • ~ likewise, I couldn't get my head around SQL Server ##temp_tables as well. :) Admittedly, I'd rather have an implementation as per Oracle's, but if that's simply not possible in SQL Server, then your suggestion/s seem to make the most sense. Thanks! +1 – Richard Neil Ilagan Sep 13 '10 at 00:08
  • I have a coworker who has found a use for ##temp_tables - he uses SSIS for some processes and if you use ## in one proc, and that proc calls another proc, proc#2 can use the ##temp_table. – user158017 Sep 15 '10 at 20:24
  • @sql_mommy: I had a coworker who did a similar thing, in that they were using ##tables to use accross procs. However, they had no way of stopping the end users from kicking off the same process while someone else was already running, so ran the risk that the work from the two users would get mixed together in the global temp table. We moved the temp table definitions to the top proc, so all called procs could see them and made them local temp tables. For SSIS, if it is a batch process that is kicked off by a job, probably OK. – Shannon Severance Sep 15 '10 at 21:49
1

This is off topic but did you know that in SQL Server you can create a temp table like this:

select *
into #temp_table
from mytable
codingguy3000
  • 2,667
  • 14
  • 38
  • 68
1

Temp tables in SQL can be very useful when you need to merge data from different sources that have a common merge field, but where you need to sum amounts prior to merging in order to compare net totals for the two sources. In a financial system that's useful. I was disappointed when we moved from SQL Server to Oracle because I lost that functionality.

The example below is for a PeopleSoft financials implementation. The budget module (KK tables) and general ledger (journal) should have the same balances for a fund once the interface has been run between the two. The query below totals budget amounts by fund from the KK tables and stores those in a temp table, then totals corresponding amounts by fund from the general ledger , then merges the two pre-summed data tables to allow comparison of the net amount per fund from the two sources--and lists results only when there is a difference between amounts for a fund. In that case, budget and GL modules are out of sync. This is actually a pretty elegant solution and there was no need to create a global temp table available to others for this query/report.

I hope someone finds this useful. It helped me at the time.

/*** START NESTED QUERY #1                                             ***/
/*** THE FOLLOWING CREATES TWO TEMP TABLES WITH NET AVAILABLE PER FUND ***/
/*** WITH ONE AMOUNT BASED ON KK TABLES AND ONE AMOUNT BASED ON        ***/
/*** BUDGETARY GL BALANCES. THEN TEMP TABLES ARE MERGED BY FUND AND    ***/
/*** NET DIFFERENCE CALCULATED-SELECTING  FUNDS WITH DIFFERENCES.      ***/
/*** IF BUDGET CHECKING IS COMPLETE AND JOURNALS CREATED AND POSTED    ***/
/*** THERE SHOULD BE NO DIFFERENCES.                                   ***/

--create a temp table with journal amounts summed by fund code
CREATE TABLE #JRNLsum(
FUND_CODE char(5),
JRNLAMT decimal(19,2) )
INSERT INTO #JRNLsum (FUND_CODE, JRNLAMT)
select FUND_CODE, sum(MONETARY_AMOUNT * -1) JRNLAMT 
FROM PS_JRNL_LN 
INNER JOIN PS_JRNL_HEADER 
ON PS_JRNL_LN.JOURNAL_ID = PS_JRNL_HEADER.JOURNAL_ID 
where ((ACCOUNT BETWEEN 430000 and 469999) and (FISCAL_YEAR >= '2009')) 
GROUP BY FUND_CODE order by FUND_CODE


--create a temp table with KK ledger amounts summed by fund code
CREATE TABLE #KKsum(
FUND_CODE char(5),
KKAMT decimal(19,2) )
INSERT INTO #KKsum (FUND_CODE, KKAMT) 
select FUND_CODE, sum(POSTED_TOTAL_AMT  * -1) KKAMT
from PS_LEDGER_KK where LEDGER like 'FUND_%'
group by FUND_CODE order by FUND_CODE

--join kk temp date to journal temp data, keep only
--fund code, kk net amount, and journal net amount
--and select only fund codes where there is a difference
--between kk net amount and journal net amount
select #KKsum.FUND_CODE, JRNLAMT, KKAMT from #JRNLsum
INNER JOIN #KKsum
on #KKsum.FUND_CODE=#JRNLsum.FUND_CODE 
where (JRNLAMT - KKAMT) <> 0.00


--drop the two temp tables
drop table #KKsum
drop table #JRNLsum

/*** END NESTED QUERY #1