Drop table in Stored Procedure not working properly? - sql-server

I have a stored procedure which drops a table if it exists, then it re-creates the table & fills it with relevant data, a friend of mine has about the same code, the only real difference is in the column headers for the table.
As an illustration, here's how mine looks (not really, just a representation).
+----+-----+-----+--------+
| ID | Foo | Bar | Number |
+----+-----+-----+--------+
| 1 | x | x | 0 |
| 2 | x | x | 1 |
+----+-----+-----+--------+
And here's what his might look like
+----+--------+--------+-----+--------+
| ID | BarFoo | FooBar | Num | Suffix |
+----+--------+--------+-----+--------+
| 1 | x | x | 0 | a |
| 2 | x | x | 1 | b |
+----+--------+--------+-----+--------+
Again, these are merely representations of the situation.
As this is to be a school assignment, the teacher will be creating & executing both SP's, however when creating the SP after using another, I get this error:
Msg 207, Level 16, State 1, Procedure XYZ, Line 59
Invalid column name 'Foo'.
Msg 213, Level 16, State 1, Procedure XYZ, Line 61
Column name or number of supplied values does not match table definition.
However, at the start of both stored procedures, we have this:
CREATE PROCEDURE XYZ
AS
BEGIN
IF EXISTS (SELECT name
FROM sysobjects
WHERE name = 'TABLENAME'
AND xtype = 'u')
DROP TABLE TABLENAME;
From what I understand, this should remove the entire table? Including table/column definitions & data?
The only fix I've found so far, is to either execute the DROP TABLE separately before creating the stored procedure, which won't work for us as it really has to be within the stored procedure.
Help would be much appreciated :)
EDIT: Here's my ACTUAL code, apart from comments, this is exactly how it looks in my script (excluding other code behind it).
IF EXISTS (SELECT name
FROM sysobjects
WHERE name = 'BerekenStatistiek'
AND xtype = 'p')
DROP PROCEDURE BerekenStatistiek;
GO
CREATE PROCEDURE BerekenStatistiek
#jaar INT=0
AS
BEGIN
IF EXISTS (SELECT name
FROM sysobjects
WHERE name = 'Statistiek'
AND xtype = 'u')
DROP TABLE Statistiek;
DECLARE #year AS NVARCHAR (4);
SET #year = CONVERT (NVARCHAR (4), #jaar);
SELECT *,
CAST (Kost - Korting + Freight AS MONEY) AS Netto,
'' AS Richting
INTO Statistiek
FROM (SELECT O.Kwartaal,
CAST (SUM(O.Kost) AS MONEY) AS Kost,
CAST (SUM(O.Korting) AS MONEY) AS Korting,
CAST (SUM(O.Freight) AS MONEY) AS Freight
FROM (SELECT CASE
WHEN CONVERT (NVARCHAR (8), OrderDate, 112) BETWEEN #year + '0101' AND #year + '0331' THEN 1
WHEN CONVERT (NVARCHAR (8), OrderDate, 112) BETWEEN #year + '0401' AND #year + '0630' THEN 2
WHEN CONVERT (NVARCHAR (8), OrderDate, 112) BETWEEN #year + '0701' AND #year + '0930' THEN 3
WHEN CONVERT (NVARCHAR (8), OrderDate, 112) BETWEEN #year + '1001' AND #year + '1231' THEN 4
END AS 'Kwartaal',
ROUND(UnitPrice * Quantity, 2) AS Kost,
Round((UnitPrice * Quantity) * Discount, 2) AS Korting,
Freight
FROM Orders AS O
INNER JOIN
OrderDetails AS Od
ON O.OrderID = Od.OrderID
WHERE CONVERT (NVARCHAR (4), OrderDate, 112) = #year) AS O
GROUP BY O.Kwartaal) AS O1;
ALTER TABLE Statistiek ALTER COLUMN Kwartaal INT NOT NULL;
ALTER TABLE Statistiek ALTER COLUMN Richting NVARCHAR (8);
ALTER TABLE Statistiek
ADD PRIMARY KEY (Kwartaal);
...
And here's his code (the insertion of values in the variables are excluded just for readability (his code is a bit more bulky):
IF EXISTS (SELECT name
FROM sysobjects
WHERE name = 'BerekenStatistiek'
AND xtype = 'p')
BEGIN
DROP PROCEDURE BerekenStatistiek;
END
GO
CREATE PROCEDURE BerekenStatistiek
#jaartal INT
AS
BEGIN
DECLARE #huidigkwartaal AS INT = 1;
DECLARE #beginmaand AS INT;
DECLARE #eindmaand AS INT;
DECLARE #vorige_netto_ontvangsten AS MONEY;
IF EXISTS (SELECT *
FROM sysobjects
WHERE name = 'Statistiek'
AND xtype = 'U')
BEGIN
DROP TABLE Statistiek;
END
CREATE TABLE Statistiek
(
kwartaalnummer INT ,
beginmaand INT ,
eindmaand INT ,
orderbedrag MONEY ,
korting MONEY ,
vervoerskost MONEY ,
netto_ontvangsten MONEY ,
stijgend_dalend_gelijk NVARCHAR (10)
);
--Variables get their data here.
INSERT INTO Statistiek (kwartaalnummer, beginmaand, eindmaand, orderbedrag, korting, vervoerskost, netto_ontvangsten, stijgend_dalend_gelijk)
VALUES (#huidigkwartaal, #beginmaand, #eindmaand, #orderbedrag, #korting, #vervoerskost, #netto_ontvangsten, #stijgend_dalend_gelijk);

"however when creating the SP after using another, I get this error" (Emphasis added.)
SQL Server will insist that a stored procedure match the definitions of tables that exist as the time the stored procedure is created. If the table does not exist when the stored procedure is created, SQL Server will assume that a matching table will appear at run time.
create table t (c int)
go
create procedure p as begin
drop table t
select 1 as diff_column_name into t
select diff_colun_name from t
end
results in:
Msg 207, Level 16, State 1, Procedure p, Line 6
Invalid column name 'diff_colun_name'.
Now, drop table t, and the procedure cane be created:
drop table t
go
create procedure p as begin
drop table t
select 1 as diff_column_name into t
select diff_colun_name from t
end
Command(s) completed successfully.

If you can use a different table name, start with that. And, if the table has to exist only for a moment after the proc is executed so that it can be selected from, then create a global temporary table (i.e. table name starts with ## as in ##MyTable).
However, if it is a requirement to use the same table name as your classmate, then the teacher is probably trying to get you to learn about deferred object resolution (i.e. #Shannon's answer) and how to get around it, because outside of learning this, the scenario makes no sense since one would never do such a thing in reality.
Sub-processes (i.e. EXEC and sp_executesql) do not resolve immediately since they aren't executed when creating the stored procedure. So, simplistically, just declare a new NVARCHAR(MAX) variable to hold some Dynamic SQL and put your SELECT statement in there. Use sp_executesql to pass in the #year variable. You are creating a real table so it will survive beyond the subprocess ending and then the ALTER TABLE statement will work.
Additional notes:
You don't really need the ALTER statement to set the datatype of the [Richting] field. Just tell SQL Server what the type is in your SELECT statement:
CONVERT(NVARCHAR(8), '') AS [Richting]
You don't really want to do CONVERT(NVARCHAR(8), OrderDate, 112) to compare to a value as it invalidates the use of any indexes that might be on [OrderDate]. Instead, construct a date value from the strings and convert that to a DATETIME or DATE (i.e. CONVERT(DATETIME, #year + '0101')).
To better understand this issue, please read Sargability: Why %string% Is Slow, and at least the first link at the bottom, which is: What makes a SQL statement sargable?
You don't really want to convert the OrderDate field to NVARCHAR(4) just to compare the year, for the same reason as just mentioned in the above point. At the very least using the YEAR() function would be more direct. But if you want to make sure indexes can be used, you can't put a function on the field. But you only want the year. So isn't the year the same as BETWEEN #Year + '0101' AND #Year + '1231'? ;-)
Interestingly enough, the first example in the accepted answer in the "What makes a SQL statement sargable?" S.O. question linked in the previous bullet is exactly what I am recommending here :).

For I can understand, the wrong queries are the inserts, because the engine can't find correct table structure, check if the inserts have the same structure of your second table example. Dont forget to check the USE at the beginning of the script, maybe you are using a different db, this can happen :).

In the last bit of code, you are having
AND xtype = 'U'
If your collation is case sensitive, the drop is not taking place and thus the error.

Related

Dynamic query with variable value from a table in SSIS 2015

I have Table A that has only one row :
CODE | DATE
202211 | 2022-11
this table will update it self automatically every end of the month (eg: Next month it will change to 202212 and 2022-12)
I want to use 'CODE' and 'DATE' to make my query dynamic, using variable and Execute SQL Task in SSIS.
My original query look like this :
SELECT * FROM X
WHERE PERIOD = '202211', EXPDATE > '2022-11'
I want to make it so that whenever Table A change, I don't have to change the Query too.
This is what I tried already :
DECLARE #Period varchar(50)
DECLARE #Expdate varchar(50)
SET #Period = ?
SET #Expdate = ?
SELECT * FROM X
WHERE PERIOD = #Period, EXPDATE > #Expdate
When I try to run using '?' just as the documentation say, it doesn't work, but it run when I change the '?' into hardcode, so I'm pretty sure at least my query works. Am I missing something, or I'm setting the Variable wrong.
This is my variable settings
Name | Scope | Data type | Value | Expression
position | MyDtsx | String | |
date | MyDtsx | String | |
This is my SQL Task setting
General
__________________________
Result Set = Single Row
SQLSourceType = Direct Input
SQLStatement = 'SELECT CODE as position, DATE as date FROM A'
Result Set
__________________________
Result Name | Variable Name
position | User::position
date | User::date
You have invalid syntax
SELECT *
FROM X
WHERE PERIOD = #Period, EXPDATE > #Expdate
Make that
SELECT *
FROM X
WHERE PERIOD = #Period AND EXPDATE > #Expdate
However, if table A (the source of Period and ExpDate) is in the same database as table X, skip the extraneous Execute SQL Task and the variables and just make the query
SELECT X.*
FROM X
WHERE EXISTS (SELECT *
FROM A
WHERE X.PERIOD = A.Code AND X.EXPDATE > P.[Date]);
The comment indicates
Table A and Table X is from a different database. Sadly the query is actually fine since when I change it to' #Period = '202211'' and '#Expdate = '2022-11'' it run.
A working repo.
My working notes for those following along at home as the name changes messed me a few times.
Table A's Code = SSIS Variable position = Table X's Period
Table A's Date = SSIS Variable date = Table X's ExpDate
SQL Setup
Execute sql task to ensure I have data
drop table if exists dbo.so_74394641;
create table dbo.so_74394641
(
Col1 bigint, Period varchar(50), ExpDate varchar(50)
);
insert into dbo.so_74394641
SELECT row_number() over (order by (SELECT NULL)) AS col1, '202211', '2022-12'
FROM sys.all_objects;
SQL Get Values
Execute sql task. Hard coded as I didn't want to create another table in a different database
SELECT '202211' AS Code, '2022-11' AS [Date];
DFT Get Data
A data flow. OLE DB Source component using the following query
DECLARE #Period varchar(50)
DECLARE #Expdate varchar(50)
SET #Period = ?
SET #Expdate = ?
SELECT * FROM dbo.SO_74394641 AS X
WHERE PERIOD = #Period and EXPDATE > #Expdate;
Parameters mapped
0 User::dosition Input
1 User::date Input
Control flow
Data Flow

Splitting column value by '\' in Sql server

I have some data in FileFullPath Column
Y:\dfs-dc-01\Split\Retail\Kroger\Kroger\FTP-FromClient\Oracle\2022-05-04\MSudaitemlov_20220503
Y:\dfs-dc-01\Split\Retail\Kroger\Kroger\FTP-FromClient\OracleABC\2022-05-04\FDERDMSudaitemlov_20220503
Y:\dfs-dc-01\Split\Retail\Kroger\Kroger\FTP-FromClient\OCSBAGF\2022-05-04\AASSSMSudaitemlov_20220503
The part I wanted is:
Oracle
OracleABC
OCSBAGF
The letters are dynamic so, I couldn't apply Left,Right function since the length is different. I tried to split it using '\' by using STRING_SPLIT() but it's saying:
Msg 195, Level 15, State 10, Line 18
'string_split' is not a recognized built-in function name.
You should be able to use STRING_SPLIT() in SQL Server 2016, except in two scenarios:
If you're not calling the function correctly - many people try to call it like a scalar function (SELECT STRING_SPLIT(...) instead of a table-valued function (SELECT * FROM STRING_SPLIT(...). It returns a table, so you must treat it like a table.
If your database's compatibility level is lower than 130. This is called out at the very top of the documentation, and I've given several workarounds in this tip in cases where you can't change compat level.
But STRING_SPLIT() won't solve this problem anyway...
...because the output order is not guaranteed, so you could never reliably determine which element is 3rd from last.
Borrowing shamelessly from my work in this article, you can create the following simple function:
CREATE FUNCTION dbo.SplitOrdered_JSON
(
#List nvarchar(4000),
#Delimiter nvarchar(255)
)
RETURNS table WITH SCHEMABINDING
AS
RETURN
(
SELECT [key], value FROM OPENJSON
(
CONCAT
(
N'["',
REPLACE(STRING_ESCAPE(#List, 'JSON'),
#Delimiter, N'","'),
N'"]')
) AS x
);
Then if you're after the 3rd-last element in the string, you can just reverse before parsing, and then reverse again after parsing. e.g.
CREATE TABLE #f(ID int, FullFilePath nvarchar(4000));
INSERT #f VALUES
(1,N'Y:\dfs-dc-01\Split\Retail\Kroger\Kroger\FTP-FromClient\Oracle\2022-05-04\MSudaitemlov_20220503'),
(2,N'Y:\dfs-dc-01\Split\Retail\Kroger\Kroger\FTP-FromClient\OracleABC\2022-05-04\FDERDMSudaitemlov_20220503'),
(3,N'Y:\dfs-dc-01\Split\Retail\Kroger\Kroger\FTP-FromClient\OCSBAGF\2022-05-04\AASSSMSudaitemlov_20220503');
DECLARE #ElementOfInterest int = 3;
SELECT REVERSE(value)
FROM #f CROSS APPLY dbo.SplitOrdered_JSON(REVERSE(FullFilePath), N'\')
WHERE [key] = #ElementOfInterest - 1;
Example db<>fiddle
Here is another solution for a complete coverage.
It will work starting from SQL Server 2012 onwards.
It is using XML and XQuery for tokenization. No need in any User-Defined-Function (UDF).
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, FullFilePath nvarchar(4000));
INSERT INTO #tbl (FullFilePath) VALUES
(N'Y:\dfs-dc-01\Split\Retail\Kroger\Kroger\FTP-FromClient\Oracle\2022-05-04\MSudaitemlov_20220503'),
(N'Y:\dfs-dc-01\Split\Retail\Kroger\Kroger\FTP-FromClient\OracleABC\2022-05-04\FDERDMSudaitemlov_20220503'),
(N'Y:\dfs-dc-01\Split\Retail\Kroger\Kroger\FTP-FromClient\OCSBAGF\2022-05-04\AASSSMSudaitemlov_20220503');
-- DDL and sample data population, end
DECLARE #separator CHAR(1) = '\'
, #token int = 8;
SELECT t.*
, c.value('(/root/r[sql:variable("#token")]/text())[1]', 'NVARCHAR(20)')
FROM #tbl AS t
CROSS APPLY (SELECT TRY_CAST('<root><r><![CDATA[' +
REPLACE(FullFilePath, #separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML)) AS t1(c);
Output
+----+--------------------------------------------------------------------------------------------------------+------------------+
| ID | FullFilePath | (No column name) |
+----+--------------------------------------------------------------------------------------------------------+------------------+
| 1 | Y:\dfs-dc-01\Split\Retail\Kroger\Kroger\FTP-FromClient\Oracle\2022-05-04\MSudaitemlov_20220503 | Oracle |
| 2 | Y:\dfs-dc-01\Split\Retail\Kroger\Kroger\FTP-FromClient\OracleABC\2022-05-04\FDERDMSudaitemlov_20220503 | OracleABC |
| 3 | Y:\dfs-dc-01\Split\Retail\Kroger\Kroger\FTP-FromClient\OCSBAGF\2022-05-04\AASSSMSudaitemlov_20220503 | OCSBAGF |
+----+--------------------------------------------------------------------------------------------------------+------------------+

SQL: How to refer to a dynamic column name to make calculation

I'd like to update fields while referring to a dynamic column.
The goal is to automate a process because each month the column to refer to changes.
For example it's like having different columns like month1, month2, month3 until month24. Each month, only 1 column needs to be updated but it's a running number that is calculated in another table.
So my question is how to make the query dynamic so that every month i only update the column number that i want and not the other one.
I tried the script below but the following issue comes up
Error converting data type varchar to float.
DECLARE #PromoMonthNumber VARCHAR(60)
DECLARE #PromoMonth VARCHAR(600)
SET #PromoMonthNumber = (SELECT CurrentDemandIndex FROM RidgeSys) --This refer to a number that change all the time
SET #PromoMonth = 'SELECT ABC.PromotionHistory' + #PromoMonthNumber
UPDATE ABC
SET #PromoMonth = table2.promotionhistory
FROM ABC
INNER JOIN (
SELECT Article.code as code, sum(ROUND(#PromoMonth,0)) as promotionhistory
FROM Article
INNER JOIN ABC ON DEF.articlecode = ABC.Articlecode
) as table2
ON ABC.articlecode = table2.code)
Here is your issue:
SELECT Article.code as code, sum(ROUND(#PromoMonth,0)) as promotionhistory
Since #PromoMonth is defined as VARCHAR, if the value is non-numeric, it will fail. Here is an example:
This works fine:
declare #x varchar(100) = '1';
select sum(round(#x,0));
Result:
1
This fails with same error above:
declare #x varchar(100) = 'x';
select sum(round(#x,0));
Result:
Msg 8114, Level 16, State 5, Line 3
Error converting data type varchar to float.
You need to check that the value is numeric before you do the calculation.

Testing condition before inserting records SQL server

I have a stored procedure in SQL Server that inserts records for actual expenses into a table. When the procedure is invoked the month in question is specified as part of of a variable. For example:
exec dbo.upsert_actuals_load_01_load_data 4
When the code runs it's supposed to insert the records into the column that corresponds to the month. '1' inserts values into jan_amt, '2' inserts values into feb_amt, etc.
I have written this code:
IF #month = 1
INSERT INTO #actuals_b
([forecast_yr_id]
,[entry_type]
,[unit_cd]
,[proj_nbr]
,[jan_amt]
,[feb_amt]
,[mar_amt]
...])
SELECT forecast_yr_id
, entry_type
, unit_cd
, proj_nbr
, month_amt AS jan_amt
, 0 AS feb_amt
, 0 AS mar_amt
....
FROM #actuals;
It seems inefficient to have to write the INSERT INTO statement for each IF #month = condition. Is there a better way to do this?
To expand on my comment, the correct design of your table should be something along the lines of:
--All data types are complete guesses
CREATE TABLE actuals_b ([forecast_yr_id] int,
[entry_type] varchar(10),
[unit_cd] varchar(10),
[proj_nbr] int,
MonthNum int,
Amount decimal(12,2)
...)
Then, instead of an IF...ELSE or CASE expressions, your INSERT becomes a much simpler:
INSERT INTO actuals_b([forecast_yr_id],[entry_type],[unit_cd],[proj_nbr],MonthNum,Amount,...)
SELECT forecast_yr_id,
entry_type,
unit_cd,
proj_nbr,
#month,
month_amt,
...
FROM actuals;
(Note this is pseudo-SQL in the absence of a full table definition).
I agree with Larnu here... but you could build this out dynamically if you use a global temp table in both cases (or real tables)... something like:
declare #column varchar(64) =
case
when #month = 1 then '[jan_amt]'
when #month = 2 then '[feb_amt]'
...
end
create table ##actuals_b (...your table definition...)
declare #sql varchar(max) = '
INSERT INTO ##actuals_b
([forecast_yr_id]
,[entry_type]
,[unit_cd]
,[proj_nbr]
,' + #column = ') select * from ##actuals'
print(#sql)
This assumes ##actuals only has a single amt column, which seems to be the case based off your static values for the other months.

MS SQL Stored Procedure Problem

I have a stored procedure that works fine on my local SQL Server (2005 or 2008 cant recall off hand) but fails when I try to create the procedure on the Production server (SQL 2000).
Any help would be appreciated. TIA.
The stored procedure declaration is this:
/****** Object: StoredProcedure [dbo].[AssignPCSCheckNumbers] Script Date: 06/29/2009 13:12:24 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[AssignPCSCheckNumbers]
(
#MonthEnd DATETIME,
#Seed INT,
#ManifestKey UNIQUEIDENTIFIER,
#Threshold DECIMAL(9,2)
)
AS
SET NOCOUNT ON
BEGIN
--Create a temporary table variable to store our data
DECLARE #MyTemp TABLE
(
ProducerNumber VARCHAR(20),
LastCheckDate DATETIME,
Due DECIMAL(9,2) DEFAULT 0,
Returned DECIMAL(9,2) DEFAULT 0
)
--Fill the table with a listing of producers from our PCSItems table and their ACH Status
INSERT INTO #MyTemp ( ProducerNumber )
SELECT PCSItems.ProducerNumber
FROM PCSItems
LEFT JOIN Producer
ON PCSItems.ProducerNumber = Producer.prodNum
WHERE ISNULL(Producer.PayCommissionByACH,0) = 0
--UPDATE the table with the last time a check was printed for each
--of these producers
UPDATE #MyTemp
SET LastCheckDate = (
SELECT ISNULL(MAX(EntryDate),'1/1/1901')
FROM CommissionLedger WITH (NOLOCK)
WHERE CommissionLedger.TransactionType = 1
AND CommissionLedger.ProducerNumber = [#MyTemp].ProducerNumber
)
--update the table with the amount of comission owed to each producer
UPDATE #MyTemp
SET Due = (
SELECT IsNull(SUM(CommPaid),0)
FROM ProducerComm WITH (NOLOCK)
WHERE ProducerComm.CommApplies = [#MyTemp].ProducerNumber
AND ProducerComm.EntryDate >= LastCheckDate
AND ProducerComm.EntryDate <= #MonthEnd
)
--update the table with the amount of commission returned by each producer
UPDATE #MyTemp
SET Returned = (
SELECT ISNULL(SUM(Amount), 0)
FROM CommissionLedger WITH (NOLOCK)
WHERE CommissionLedger.ProducerNumber = [#MyTemp].ProducerNumber
AND CommissionLedger.EntryDate >= [#MyTemp].LastCheckDate
AND CommissionLedger.EntryDate <= #MonthEnd
)
--create a table to assist with our operations
DECLARE #MyFinal TABLE
(
ID INT IDENTITY(1,1),
ProducerNumber VARCHAR(10)
)
--just insert the producers that are owed an amount over a user specified
--threshold
INSERT INTO #MyFinal ( ProducerNumber )
SELECT ProducerNumber
FROM #MyTemp
WHERE (Due + Returned) > #Threshold
--update our items with the check numbers finally =)
UPDATE PCSItems
SET CheckNumber = (SELECT (([#MyFinal].ID - 1) + #Seed)
FROM #MyFinal
WHERE [#MyFinal].ProducerNumber = PCSItems.ProducerNumber)
SET NOCOUNT OFF
END
GO
And the error the server responds with is this:
Msg 107, Level 16, State 2, Procedure AssignPCSCheckNumbers, Line 35
The column prefix '#MyTemp' does not match with a table name or alias name used in the query.
Msg 107, Level 16, State 2, Procedure AssignPCSCheckNumbers, Line 45
The column prefix '#MyTemp' does not match with a table name or alias name used in the query.
Msg 107, Level 16, State 2, Procedure AssignPCSCheckNumbers, Line 55
The column prefix '#MyTemp' does not match with a table name or alias name used in the query.
Msg 107, Level 16, State 2, Procedure AssignPCSCheckNumbers, Line 55
The column prefix '#MyTemp' does not match with a table name or alias name used in the query.
Msg 107, Level 16, State 2, Procedure AssignPCSCheckNumbers, Line 79
The column prefix '#MyFinal' does not match with a table name or alias name used in the query.
Msg 107, Level 16, State 2, Procedure AssignPCSCheckNumbers, Line 79
The column prefix '#MyFinal' does not match with a table name or alias name used in the query.
That should be created no problem on a 2000 box (and I verified by creating it on my sql 2000 box). Are you sure your database is not in 7.0 compatibility mode?
run
sp_helpdb 'YourDatabaseName'
and look if compatability is 80
I was not aware that 2000 supported table variables, as I suspected in my first answer.
Now I tried in Query Analyzer and found that #table is handled differently from [#table] which results in an error message "invalid object name #table".
I suggest to remove the square brackets from the # table names.
update:
This page indicates using a table alias might fix the problem. I just experimented with:
UPDATE #a SET a = a + b FROM #a INNER JOIN #b ON #a.a = #b.b
which failed with an error. Rewriting as
UPDATE #a SET a = a + b FROM #a aa INNER JOIN #b bb ON aa.a = bb.b
works. Hope it works for you too ;)
This is loosely quoted from a question I asked awhile ago (Link) so if it works for you, upvote Mike L's response instead of mine.
If you use the Database Publishing Wizard to create scripts for your SPs, you can build them in 2005 and use it to deploy to 2000 letting the wizard take care of any compatability issues you may have.
It's not the # notation that is causing the problem, it's the brackets #a not [#a].
It's been a while but I seem to remember SQL 2000 requiring you to use an alias when you are referencing the table in both the update statement and in a subquery. Hope this helps or you find the solution.
AFAIK tables in where clause can't referenced by name and you should their alias for this purpose, in MSSQL2000 book online for search condition we see:
<search_condition>:=
{ constant
| scalar_function
| [ alias. ] column
| local_variable
| ( expression )
| ( scalar_subquery )
| { unary_operator } expression
| expression { binary_operator } expression
}
and as you see, there is no table or alias and it is only alias

Resources