SQL Server Global Temporary Table Locking - sql

How do I lock a global temporary table in a stored procedure that's getting created and populated by a SELECT INTO statement? For example:
SELECT *
INTO ##TempEmployee
FROM Employee
This stored procedure is executed for generating reports and it's there in every client database (multi-tenant architecture using different DB per client). I do not want data in this global temporary table to be shared between clients when the report is generated concurrently. I don't have a choice but to use global temp table because I use it for generating columns on the fly using PIVOT.

Why not include it inside a transaction block like
begin transaction
SELECT *
INTO ##TempEmployee
FROM Employee

Try this,
WorkDummySQL
create table rr(id integer,name varchar(20))
insert into rr values(1,'aa')
select * from rr
Tempdb
select * into ##ta from WorkDummySQL.dbo.rr

Related

BigQuery create Temp table

I am trying to create a temporary table with a specific name so i can use it in other queries. The problem is that when i create a temp table like this:
BEGIN
BEGIN TRANSACTION;
--delete test_temp where 1=1;
create temp table test_temp as SELECT * FROM `analytics.reports.analysis` ;
COMMIT TRANSACTION;
END;
the table name is indeed test_temp but if i will try to select * from test_temp
i get nothing. the table id always generates a new unique id.
something like analytics-prod:_script3991beb3e9868774854ac09d407f1c397428a4f6.test_temp
Is there a way to make this temp table with a pre-defined name?
What I am trying to achieve basically is create a table from a select every 15min.
I thought to create a scheduled query running this transaction that will delete + populate the temp table and then I can always reference to test_temp without changing the table id.
According to the docs:
You can refer to a temporary table by name for the duration of the current multi-statement query
So if you want to refer the table in other queries, an option could be use a permanent table in a separated dataset:
...
CREATE OR REPLACE TABLE `analytics.my_temp_dataset.test_temp` AS SELECT * FROM `analytics.reports.analysis` ;
...
In that case, you don't need a temp table but a permanent table you just replace on the next run using the CREATE OR REPLACE TABLE statement. If you are using the temp table as part of a scripting stage, then I suggest using running this instead:
BEGIN
CREATE OR REPLACE TEMP TABLE _SESSION.test_temp AS
SELECT * FROM `analytics.reports.analysis`;
-- SELECT COUNT(*) CNT FROM _SESSION.test_temp;
END;
Since it is a temp table you don't need a DROP query at the end.
You can create a temporary table in a session in BigQuery.
You can create a session via the API and then create your temporary tables in the session. The tables will then be visible to all queries using that session.
There are limitations on sessions you should be aware of:
They last up to 24 hours max
No concurrent jobs running in a session
I use temporary tables with sessions to do complex transformations in an ETL pipeline. For example:
Create session
Create temporary tables
Do joins, and other transformations, write results to temporary tables
Do final transformations and output results to permanent tables
End session
I am writing a Python API for this and will put it on github at some point. I could probably post a gist if that is helpful.
In the meantime, see Google's documentation for sessions in BigQuery:
https://cloud.google.com/bigquery/docs/sessions-intro

The multi-part identifier "##ABMPARENT.SYM_INDEX" could not be bound

I'm running the code below in SQL server 2012 and am getting an error msg saying that
"The multi-part identifier "##ABMPARENT.SYM_INDEX" could not be bound."
I've looked through several over related threads which usually result in someone having spelt the table name incorrectly, used the where clause more than once in a single select statement etc ... However I've used the intellisense and have referenced the correct column / table as far as I can see.
Can anybody tell what is causing the error?
Thanks
Ps. I don't have access to save a SQL view which is why I'm using temp tables for this.
IF OBJECT_ID('tempdb..#ABMPARENT') IS NOT NULL
DROP TABLE ##ABMPARENT
IF OBJECT_ID('tempdb..#ALLSYMBOLS') IS NOT NULL
DROP TABLE ##ALLSYMBOLS
SELECT dbo.KLX_PARENT_CHILD.PARENT_NAME ,
dbo.KLX_MASTER_SYMBOL.SYM_INDEX ,
dbo.KLX_MASTER_SYMBOL.SYM_NAME ,
dbo.KLX_SYM_DESC.DESCRIPTION
INTO ##ABMPARENT
FROM dbo.KLX_PARENT_CHILD
INNER JOIN dbo.KLX_MASTER_SYMBOL ON dbo.KLX_PARENT_CHILD.SYM_INDEX = dbo.KLX_MASTER_SYMBOL.SYM_INDEX
INNER JOIN dbo.KLX_SYM_DESC ON dbo.KLX_MASTER_SYMBOL.SYM_INDEX = dbo.KLX_SYM_DESC.MICRO_OBJ_ID
WHERE ( dbo.KLX_PARENT_CHILD.PARENT_NAME = 'ABMRCTREE_1314' )
AND ( dbo.KLX_MASTER_SYMBOL.SYM_NAME LIKE 'LVRC%' )
SELECT dbo.KLX_PARENT_CHILD.PARENT_NAME ,
dbo.KLX_MASTER_SYMBOL.SYM_INDEX ,
dbo.KLX_MASTER_SYMBOL.SYM_NAME ,
dbo.KLX_SYM_DESC.DESCRIPTION ,
dbo.KLX_PARENT_CHILD.PARENT_INDEX
INTO ##ALLSYMBOLS
FROM dbo.KLX_PARENT_CHILD
INNER JOIN dbo.KLX_MASTER_SYMBOL ON dbo.KLX_PARENT_CHILD.SYM_INDEX = dbo.KLX_MASTER_SYMBOL.SYM_INDEX
INNER JOIN dbo.KLX_SYM_DESC ON dbo.KLX_MASTER_SYMBOL.SYM_INDEX = dbo.KLX_SYM_DESC.MICRO_OBJ_ID
SELECT *
FROM ##ALLSYMBOLS
where [##ABMPARENT].SYM_INDEX = ##ALLSYMBOLS.PARENT_INDEX
Your statement SELECT * FROM ##ALLSYMBOLS where [##ABMPARENT].SYM_INDEX = ##ALLSYMBOLS.PARENT_INDEX does not reference a table named [##ABMPARENT], so you cannot reference a column of that table. Did you intend to do a join in that query?
What #Gabe said. Your last select statment is referencing a table that is not in the from clause.
Nothing wrong with temp tables, but why are you using global temp tables (##some-table-name) instead of local temp tables (#some-table-name). Global temp tables are visible to every session, and are, in my experience, a code smell.
Local temp tables are scoped to to your session (or if created within a stored procedure, to a single stored procedure exection. Local temp tables are dropped when the stored procedure that created exits or when the session is closed, whichever comes first. Further, local temp table tables, once created in a stored procedure are visible to nested stored procedures -- e.g., stored procedure A creates temp table #WORK and then invokes stored procedure B which in turn invokes stored procedure C. The temp table #WORK is usable and visible to both stored procedures B and C.
It complicates stored procedure creation though. A stored procedure referencing a temp table that it doesn't create can't be created unless that temp table exists for the connection at the time create procedure is executed, so you need to do something like:
create table #foo ( ... )
go
create proc dbo.A as ...
go
drop table #foo
go
And a code suggestion: use correlation names for your tables, like so:
select *
from dbo.Foo t1
join dbo.Bar t2 on t2.id = t1.bar_id
Your SQL will be way more readable and, you only have to type the long convoluted table name once. You, your coworkers and the physical therapist you've been seeing for repetitive stress syndrome will appreciate it.

Select into tables in SQL. How are they stored?

When I run a script in PostgreSQL I usually do the following from psql:
my_database> \i my_script.sql
Where in my_script.sql I may have code like the following:
select a.run_uid, s.object_uid into temp_table from dt.table_run_group as a
inner join dt.table_segment as s on a.group_uid = s.object_uid;
In this particular case, I am only interested in creating temp_table with the results of the query.
Are these results in disk on the server? In memory? Is the table stored permanently?
Temporary tables are stored in RAM until the available memory is used up, at which time they spill onto disk. The relevant setting here is temp_buffers.
Either way, they live for the duration of a session and are dropped at the end automatically.
You can also drop them at the end of a transaction automatically (ON COMMIT DROP) or manually any time.
Temporary table are only visible to the the same user in the same session. Others cannot access it - and also not conflict with it.
Always use CREATE TABLE tbl AS .... The alternative form SELECT ... INTO tbl is discouraged since it conflicts with the INTO clause in plpgsql.
Your query could look like:
CREATE TEMP TABLE tbl AS
SELECT a.run_uid, s.object_uid
FROM dt.table_run_group a
JOIN dt.table_segment s ON a.group_uid = s.object_uid;
SELECT INTO table ... is the same as CREATE TABLE table AS ..., which creates a normal, permanent table.

Where temp tables are located?

If I create a temporary table using # sign:
SELECT * INTO #temp FROM dbo.table
Where is this table located? I can't find this from tempdb.
Those tables are created in your tempDB - but the table name might not be exactly as you defined.
In my case, I get:
#temp______________________________000000000003
Try this:
SELECT * INTO #temp FROM dbo.table
SELECT * FROM tempdb.sys.tables
You should see an entry for that temp table you've just created....
When you declare a temporary table, SQL Sever adds some additional characters on its name in order to provide a unique system name for it and then it stores it in tempDB in the sysobjects table. Even though you can query the temporary table with its logical name, internally is known with the exact name SQL Server has set.
How are you looking for them?
If you do a select you'll get the data.
But the table is only available in the session, just for the user who created it (you can have global temp tables).
They are stored in temp db.
Local temp tables can be created using hash (#) sign prior to table name.
They are visible only in current connection. When connection is dropped its scope ends as well.
It is possible to create and use local temp table with the same name simultaneously in two different connections.
Read More
http://sqlnetcode.blogspot.com/2011/11/there-is-already-object-named-temp-in.html
I suspect this issue rose from the fact that if you don't right click and refresh the 'Temporary Tables' folder, SSMS will not show you the temp table immediately.

How do you create a temporary table in an Oracle database?

I would like to create a temporary table in a Oracle database
something like
Declare table #table (int id)
In SQL server
And then populate it with a select statement
Is it possible?
Thanks
Yep, Oracle has temporary tables. Here is a link to an AskTom article describing them and here is the official oracle CREATE TABLE documentation.
However, in Oracle, only the data in a temporary table is temporary. The table is a regular object visible to other sessions. It is a bad practice to frequently create and drop temporary tables in Oracle.
CREATE GLOBAL TEMPORARY TABLE today_sales(order_id NUMBER)
ON COMMIT PRESERVE ROWS;
Oracle 18c added private temporary tables, which are single-session in-memory objects. See the documentation for more details. Private temporary tables can be dynamically created and dropped.
CREATE PRIVATE TEMPORARY TABLE ora$ptt_today_sales AS
SELECT * FROM orders WHERE order_date = SYSDATE;
Temporary tables can be useful but they are commonly abused in Oracle. They can often be avoided by combining multiple steps into a single SQL statement using inline views.
Just a tip.. Temporary tables in Oracle are different to SQL Server. You create it ONCE and only ONCE, not every session. The rows you insert into it are visible only to your session, and are automatically deleted (i.e., TRUNCATE, not DROP) when you end you session ( or end of the transaction, depending on which "ON COMMIT" clause you use).
CREATE GLOBAL TEMPORARY TABLE Table_name
(startdate DATE,
enddate DATE,
class CHAR(20))
ON COMMIT DELETE ROWS;
CREATE TABLE table_temp_list_objects AS
SELECT o.owner, o.object_name FROM sys.all_objects o WHERE o.object_type ='TABLE';