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

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.

Related

Stored procedure doesn't insert data into one of the table even though data looks good

I'm trying to insert data into two tables [Product]., it's inserting into one of the tables not inserting `[Product]. It returns an empty table. Not sure how to handle multiple inserts in the stored procedure:
Try this
INSERT INTO [Product].[LKStandardProductGroup]
([StandardProductGroupID],[StandardProductID])
SELECT
#StandardProductGroupID as [StandardProductGroupID] ,
value as [StandardProductID]
FROM STRING_SPLIT(#StandardProductCodes,',') inp
INNER JOIN [Product].[StandardProduct] sp WITH(NOLOCK)
ON sp.[StandardProductID] = inp.value

Track number of rows in a #table which the population is in progress

I am working in SQL Server 2012 Management studio.
In a SQL query window, an insert into a #table is happening. It is expected to insert somewhere around 80 million rows with 3 INT columns each.
The query execution is going on.
Is there a way that I can track the no of rows in the #table?
Since you cannot run two queries in the same window simultaneously and temp tables are not accessible in other sessions if they are declared with a single #, you should try defining it with a double # in your insert query.
Then you could try querying it using WITH(NOLOCK).
Open a new query window on the same db and try
SELECT COUNT(*)
FROM ##YourTableName WITH(NOLOCK)
This will get dirty reads, but i do not think it would be a problem in your case as you would like a rough measure on where your INSERT is.
One method is to query the DMVs using the temp table object id. You can get the local temp table object id from the session that created it using this query:
SELECT OBJECT_ID(N'tempdb..#table', 'U');
Then run the script below in another windows, supplying the object_id value from the above query (-1180342868 in this example):
DECLARE #object_id int = -1180342868;
SELECT SUM(rows)
FROM tempdb.sys.partitions
WHERE
object_id = #object_id
AND index_id IN(0,1);
Of course, this method assumes you had the foresight to get the temp table object id before running the insert. If the query is currently running, you could run the script below and make an educated guess as to which object might be the temp table being loaded.
USE tempdb;
SELECT OBJECT_NAME(object_id), SUM(rows)
FROM tempdb.sys.partitions
WHERE
index_id IN(0,1)
AND OBJECTPROPERTYEX(object_id, 'IsUserTable') = 1
GROUP BY
OBJECT_NAME(object_id);
Be aware that this might not be a reliable way to track the load progress. Much depends on the query plan particulars. It could be that the costly operators are earlier in the plan and the actual insert won't occur until the last minute.
If you wish to run the query to count rows in another window or outside the scope where the table was declared, please use a global temp table.
For Example,
CREATE TABLE ##table(
a int,
b int,
c int)
And the in another window you can run, this will work
SELECT COUNT(*) FROM ##table WITH (NOLOCK)

SQL Server Global Temporary Table Locking

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

Is there an automated way to create a temp table in SQL Server

I have a rather complex SELECT statement in a stored procedure that I am updating to insert the rows from the select into a temp table. To define the temp table, I need to know the data type of each every item selected.
Is there a easy way (a script maybe) that I can use to determine the data types and the temp table structure instead of going to each table's definition in the select to find out what it is?
PS: I can't use a Common table expression as I need to use this temp table several times within the proc
SELECT
blah
INTO
#temp
FROM
wibble
blah and wibble are not secret syntax. Please replace these with your own SQL :)
SELECT * INTO #temp FROM TABLE1
All columns in TABLE 1 gets into your temp table now

Scope of Derived Tables in SQL Server

I've been looking into SQL recently and exploring a bit. in regards to Temp Tables I have discovered 3 different temp table types:
1) CREATE TABLE #TempTable
2) DECLARE TABLE #TempTable
3) SELECT * FROM (SELECT * FROM Customers) AS TempTable
Now I understand the scope behind the #TempTable and the #TempTable types, but what about the derived table as in example 3? Where does this derived table get stored? and if it is declared in 1 transaction, can a 2nd transaction access it, or is the scoping of Derived Tables that same as example 1 and 2?
1) CREATE TABLE #TempTable --local temp table
Local temporary tables are visible only in the current session, and can be shared between nested stored procedure calls: http://www.sommarskog.se/share_data.html#temptables
2) DECLARE TABLE #TempTable --local table variable
The scope of a local variable is the batch, stored procedure, or statement block in which it is declared. They can be passed as parameters between procedures. They are not subject to transactions and will retain all rows following a rollback.
3) SELECT * FROM (SELECT * FROM Customers) AS TempTable --derived table
is visible to the current query only
4) CREATE TABLE ##TempTable --global temp table
This differs from a #temp table in that it is visible to all processes. When the creating process ends, the table is removed (but will wait until any current activity from other processes is done).
5) CTE - common table expression
example CTE:
;WITH YourBigCTE AS
(
big query here
)
SELECT * FROM YourTable1 WHERE ID IN (SELECT ID FROM YourBigCTE)
UNION
SELECT * FROM YourTable2 WHERE ID IN (SELECT ID FROM YourBigCTE)
can be used multiple times within the same CTE command, even recursively, and will last for the duration of the CTE command.
This depends on the actual RDBMS you are using - I will assume Sybase or SQL Server (but might well be true for all)
SELECT * FROM (SELECT * FROM Customers) AS TempTable
Temptable is only available for the current SQL statement ie just the select.
SELECT * FROM Customers into tempdb..TempTable
would create a new table in the tempdb whichg would have to be explicitly dropped