Hi,
I am writing a stored procedure in SQL Server 2000 the will require
multiple commits(?) during its operation. The first group of actions
that it must perform is to modify a table by adding some columns and
altering another. The next step reads data out of the table into a
temporary (in memory) table and does some processing on it and writes
it back to the original source table utilizing the recently added
columns. When I try to put this into a stored procedure, everything
after the first GO statement gets cut off, which in this case is the
guts of the procedure. Does anyone know how how to perform multiple
operatinos like this in one stored procedure?
Thanks in advance
Chris Lieb
CREATE TABLE [HRSC] (
[SEQ_NUM] [float] NULL ,
[HuReSC] [nvarchar] (18) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]
INSERT INTO [HRSC] ([SEQ_NUM], [HuReSC])
VALUES (255, 'TX750201TX769999')
INSERT INTO [HRSC] ([SEQ_NUM], [HuReSC])
VALUES (255, 'OK735001OK735002')
INSERT INTO [HRSC] ([SEQ_NUM], [HuReSC])
VALUES (255, 'LA714000')
INSERT INTO [HRSC] ([SEQ_NUM], [HuReSC])
VALUES (255, 'NM870001NM884001')
----
--
-- Add new columns to the table
ALTER TABLE
[HRSC]
ADD
[Low_State] nvarchar(3) NULL,
[Low_SLIC] nvarchar(3) NULL,
[Low_Building] nvarchar(1) NULL,
[Low_IBI] nvarchar(2) NULL,
[High_State] nvarchar(3) NULL,
[High_SLIC] nvarchar(3) NULL,
[High_Building] nvarchar(1) NULL,
[High_IBI] nvarchar(2) NULL
-- Alter the data type of the HuReSC column to be more space-efficient
ALTER TABLE
[HRSC]
ALTER COLUMN
[HuReSC] nvarchar(18)
GO
-- Prepare the temporary table
DECLARE @.hold table (
[SEQ_NUM] [float] NULL ,
[HuReSC] [nvarchar] (18) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Low_State] [nvarchar] (3) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Low_SLIC] [nvarchar] (3) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Low_Building] [nvarchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL ,
[Low_IBI] [nvarchar] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[High_State] [nvarchar] (3) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[High_SLIC] [nvarchar] (3) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[High_Building] [nvarchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL ,
[High_IBI] [nvarchar] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
)
-- Populate the temporary table with data
INSERT INTO
@.hold ([SEQ_NUM], [HuReSC])
SELECT
[SEQ_NUM],
[HuReSC]
FROM
[HRSC
-- Parse data for low end of range
UPDATE
@.hold
SET
[Low_State] = SUBSTRING([HuReSC], 1, 2),
[Low_SLIC] = SUBSTRING([HuReSC], 3, 3),
[Low_Building] = SUBSTRING([HuReSC], 6, 1),
[Low_IBI] = SUBSTRING([HuReSC], 7, 2)
-- Parse data for high end of range where needed
UPDATE
@.hold
SET
[High_State] = SUBSTRING([HuReSC], 9, 2),
[High_SLIC] = SUBSTRING([HuReSC], 11, 3),
[High_Building] = SUBSTRING([HuReSC], 14, 1),
[High_IBI] = SUBSTRING([HuReSC], 15, 2)
WHERE
LEN([HuReSC]) > 8
-- Clear the real table
TRUNCATE TABLE [HRSC]
-- Populate the table with the parsed data
INSERT INTO
[HRSC]
SELECT
*
FROM
@.hold
GOSince you know the table structure up front, why on earth are you doing
this:
CREATE TABLE
INSERT data
ALTER TABLE add columns
ALTER TABLE ALTER COLUMN but it really doesn't change
INSERT more data
Why not just
CREATE TABLE
INSERT data
The problem here is that you are saying
CREATE PROCEDURE
...do some stuff...
GO
...do more stuff...
The GO is a batch separator, and hence that is where your CREATE PROCEDURE
is completed. Everything after that has nothing to do with the stored
procedure at all. To avoid getting bitten by this, I always use the
following struct:
CREATE PROCEDURE dbo.whatever
AS
BEGIN
... code...
END
GO
Now, if I inadvertently have a GO inside the stored procedure, it won't run,
unless I have horrible code, because the BEGIN and END do not match up.
Of course, if you remove the GO, you will not be able to refer to
non-existant columns within the same batch because the parser will
read-ahead and try to match your column list to the original CREATE TABLE.
So maybe you could explain why you're creating a table, then inserting data,
then adding nullable columns, then altering a column to be the same as it
was before.
A
"Chris Lieb" <chris.lieb@.gmail.com> wrote in message
news:1133819619.878838.109740@.z14g2000cwz.googlegroups.com...
> Hi,
> I am writing a stored procedure in SQL Server 2000 the will require
> multiple commits(?) during its operation. The first group of actions
> that it must perform is to modify a table by adding some columns and
> altering another. The next step reads data out of the table into a
> temporary (in memory) table and does some processing on it and writes
> it back to the original source table utilizing the recently added
> columns. When I try to put this into a stored procedure, everything
> after the first GO statement gets cut off, which in this case is the
> guts of the procedure. Does anyone know how how to perform multiple
> operatinos like this in one stored procedure?
> Thanks in advance
> Chris Lieb
> CREATE TABLE [HRSC] (
> [SEQ_NUM] [float] NULL ,
> [HuReSC] [nvarchar] (18) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
> ) ON [PRIMARY]
> INSERT INTO [HRSC] ([SEQ_NUM], [HuReSC])
> VALUES (255, 'TX750201TX769999')
> INSERT INTO [HRSC] ([SEQ_NUM], [HuReSC])
> VALUES (255, 'OK735001OK735002')
> INSERT INTO [HRSC] ([SEQ_NUM], [HuReSC])
> VALUES (255, 'LA714000')
> INSERT INTO [HRSC] ([SEQ_NUM], [HuReSC])
> VALUES (255, 'NM870001NM884001')
> ----
--
> -- Add new columns to the table
> ALTER TABLE
> [HRSC]
> ADD
> [Low_State] nvarchar(3) NULL,
> [Low_SLIC] nvarchar(3) NULL,
> [Low_Building] nvarchar(1) NULL,
> [Low_IBI] nvarchar(2) NULL,
> [High_State] nvarchar(3) NULL,
> [High_SLIC] nvarchar(3) NULL,
> [High_Building] nvarchar(1) NULL,
> [High_IBI] nvarchar(2) NULL
> -- Alter the data type of the HuReSC column to be more space-efficient
> ALTER TABLE
> [HRSC]
> ALTER COLUMN
> [HuReSC] nvarchar(18)
> GO
> -- Prepare the temporary table
> DECLARE @.hold table (
> [SEQ_NUM] [float] NULL ,
> [HuReSC] [nvarchar] (18) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
> [Low_State] [nvarchar] (3) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
> [Low_SLIC] [nvarchar] (3) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
> [Low_Building] [nvarchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS
> NULL ,
> [Low_IBI] [nvarchar] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
> [High_State] [nvarchar] (3) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
> ,
> [High_SLIC] [nvarchar] (3) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
> [High_Building] [nvarchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS
> NULL ,
> [High_IBI] [nvarchar] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
> )
> -- Populate the temporary table with data
> INSERT INTO
> @.hold ([SEQ_NUM], [HuReSC])
> SELECT
> [SEQ_NUM],
> [HuReSC]
> FROM
> [HRSC
> -- Parse data for low end of range
> UPDATE
> @.hold
> SET
> [Low_State] = SUBSTRING([HuReSC], 1, 2),
> [Low_SLIC] = SUBSTRING([HuReSC], 3, 3),
> [Low_Building] = SUBSTRING([HuReSC], 6, 1),
> [Low_IBI] = SUBSTRING([HuReSC], 7, 2)
> -- Parse data for high end of range where needed
> UPDATE
> @.hold
> SET
> [High_State] = SUBSTRING([HuReSC], 9, 2),
> [High_SLIC] = SUBSTRING([HuReSC], 11, 3),
> [High_Building] = SUBSTRING([HuReSC], 14, 1),
> [High_IBI] = SUBSTRING([HuReSC], 15, 2)
> WHERE
> LEN([HuReSC]) > 8
> -- Clear the real table
> TRUNCATE TABLE [HRSC]
> -- Populate the table with the parsed data
> INSERT INTO
> [HRSC]
> SELECT
> *
> FROM
> @.hold
> GO
>|||Aaron Bertrand [SQL Server MVP] wrote:
> Since you know the table structure up front, why on earth are you doing
> this:
> CREATE TABLE
> INSERT data
> ALTER TABLE add columns
> ALTER TABLE ALTER COLUMN but it really doesn't change
> INSERT more data
> Why not just
> CREATE TABLE
> INSERT data
The CREATE TABLE and INSERT statements were jsut so you could get the
original table set up to play with. They are not part of the routine
that I want to perform. Also, the ALTER TABLE statement does actually
change the data type of the column, it's just that the CREATE TABLE
that I gave you had already been effected by the ALTER TABLE, so it was
incorrect. I forget the original data type, but the ALTER TABLE
statement does do something.
> The problem here is that you are saying
> CREATE PROCEDURE
> ...do some stuff...
> GO
> ...do more stuff...
> The GO is a batch separator, and hence that is where your CREATE PROCEDURE
> is completed. Everything after that has nothing to do with the stored
> procedure at all. To avoid getting bitten by this, I always use the
> following struct:
> CREATE PROCEDURE dbo.whatever
> AS
> BEGIN
> ... code...
> END
> GO
> Now, if I inadvertently have a GO inside the stored procedure, it won't ru
n,
> unless I have horrible code, because the BEGIN and END do not match up.
> Of course, if you remove the GO, you will not be able to refer to
> non-existant columns within the same batch because the parser will
> read-ahead and try to match your column list to the original CREATE TABLE.
That is exactly the point: I need to have the ALTER TABLE statements
executed before the rest so that I do not get errors. If the batch is
not committed midway, SQL Server tries to interpret the entire script
before it executes and errors saying that the columns do not exist.
> So maybe you could explain why you're creating a table, then inserting dat
a,
> then adding nullable columns, then altering a column to be the same as it
> was before.
> A
Chris Lieb|||> That is exactly the point: I need to have the ALTER TABLE statements
> executed before the rest so that I do not get errors. If the batch is
> not committed midway, SQL Server tries to interpret the entire script
> before it executes and errors saying that the columns do not exist.
Yep, and that's the way SQL Server works. There are a couple of
workarounds, such as dynamic SQL:
http://www.sommarskog.se/dynamic_sql.html
Were it my project, I would probably find a way to get the data structure
right in the first place. Ideally, I would not be changing a table's
structure every time I call a stored procedure.
A|||Do it in two simple steps:
1) fix schema - do it once, but do it right;
2) fix data - do it as many times as needed without changing the schema.
That way you can set the tables 'in concrete' once and for all and then
focus on transforming data. Or do you need to change the tables over and ove
r
again?
ML
http://milambda.blogspot.com/|||I come into this situation alot. (I do a lot of dynamic sql but don't find
that is my favourite solution.) This is a little clunky, but it has worked
for me.
I would create 4 stored procedures, for instance,
spr_DoSomething_Main
spr_DoSomething_1
spr_DoSomething_2
spr_DoSomething_3
where main just says:
exec spr_DoSomething_1
exec spr_DoSomething_2
exec spr_DoSomething_3
If I have parameters it might look like this:
Create Procedure spr_DoSomething_Main
@.Param1 int,
@.Param2 int,
@.Param3 int
AS
exec spr_DoSomething_1 @.Param1
exec spr_DoSomething_2 @.Param1, @.Param2, @.Param3
exec spr_DoSomething_3 @.Param1
go
Whatever procedure needs whatever parameters gets only them. I also
sometimes do this to use stored procedures like classes for possible code
re-use and all...
"ML" wrote:
> Do it in two simple steps:
> 1) fix schema - do it once, but do it right;
> 2) fix data - do it as many times as needed without changing the schema.
> That way you can set the tables 'in concrete' once and for all and then
> focus on transforming data. Or do you need to change the tables over and o
ver
> again?
>
> ML
> --
> http://milambda.blogspot.com/|||Aaron Bertrand [SQL Server MVP] wrote:
> Yep, and that's the way SQL Server works. There are a couple of
> workarounds, such as dynamic SQL:
> http://www.sommarskog.se/dynamic_sql.html
> Were it my project, I would probably find a way to get the data structure
> right in the first place. Ideally, I would not be changing a table's
> structure every time I call a stored procedure.
> A
OK, maybe a stored procedure isn't really the right route to have
chosen.
I am doing this to try to fix a schema that was created a few years ago
by another person who does not work here any more. I was making the
stored procedure so that once I figured out how to parse all of the
data that was on the development server, all I would have to do is have
the SP transferred to the live server and run and the data would be
fixed for me without making me go through and transform all of the data
manually. Having this on the development server also makes it easy to
fix the data when and if I need to mirror data off of the live server
in case something happens, like an error after a truncate statement
before the contents of the temp table are written back to the real
table.
Chris Lieb|||On 6 Dec 2005 06:50:39 -0800, Chris Lieb wrote:
>Aaron Bertrand [SQL Server MVP] wrote:
>OK, maybe a stored procedure isn't really the right route to have
>chosen.
>I am doing this to try to fix a schema that was created a few years ago
>by another person who does not work here any more. I was making the
>stored procedure so that once I figured out how to parse all of the
>data that was on the development server, all I would have to do is have
>the SP transferred to the live server and run and the data would be
>fixed for me without making me go through and transform all of the data
>manually. Having this on the development server also makes it easy to
>fix the data when and if I need to mirror data off of the live server
>in case something happens, like an error after a truncate statement
>before the contents of the temp table are written back to the real
>table.
>Chris Lieb
Hi Chris,
So this is a one-time job?
Instead of making a stored procedure, make an SQL script file. Store it
on your hard disk, tweak it until you're ready, then either copy and
paste into QA and execute against your prod DB or feed it through
osql.exe or a similar tool.
Unlike stored procedure's, SQL scripts can include "go", since a script
is just a load of commands sent to the server (just as if you were
typing very fast <g> ).
Best, Hugo
--
(Remove _NO_ and _SPAM_ to get my e-mail address)|||Hugo Kornelis wrote:
> On 6 Dec 2005 06:50:39 -0800, Chris Lieb wrote:
>
> Hi Chris,
> So this is a one-time job?
Once this is deployed, yes. Until then, it will be run many a time.
> Instead of making a stored procedure, make an SQL script file. Store it
> on your hard disk, tweak it until you're ready, then either copy and
> paste into QA and execute against your prod DB or feed it through
> osql.exe or a similar tool.
> Unlike stored procedure's, SQL scripts can include "go", since a script
> is just a load of commands sent to the server (just as if you were
> typing very fast <g> ).
> Best, Hugo
> --
> (Remove _NO_ and _SPAM_ to get my e-mail address)
I ended up making a DTS package out of the entire procedure, from
creating the tables, indexes, and triggers to transforming and
inserting the data.
Chris Lieb|||On 7 Dec 2005 14:35:28 -0800, Chris Lieb wrote:
(snip)
>Once this is deployed, yes. Until then, it will be run many a time.
Hi Chris,
In test, I hope <g>.
That's what I meant. A one-time job in the production DB.
>I ended up making a DTS package out of the entire procedure, from
>creating the tables, indexes, and triggers to transforming and
>inserting the data.
That's even better. My lack of experience with DTS is showing, I guess.
Best, Hugo
--
(Remove _NO_ and _SPAM_ to get my e-mail address)
Showing posts with label step. Show all posts
Showing posts with label step. Show all posts
Friday, March 9, 2012
Multiple step OLEDB Error
The error message is
-2147217887 - Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done.
It is hard to pinpoint the exact problem w/o any additional info other than just the error msg here.
The error msg itself basically indicates that the application program was passing in an OLEDB property set, one or more of the properties were causing problem. What you should do is to enumerate through the property set and examine the corresponding status value, the error status should shed light on what went wrong.
Multiple Step OLE DB error from VB
One of our users is getting this error message.
Microsoft OLE DB Provider for ODBC Drivers (0x80040E21) Multiple-step OLE DB operation
generated errors. Check each OLE DB status value, if available. No work was done.
This is the only user that is currently getting the message. Last week another user got this one day and then it stopped.
Inside VB6 code, we're sending some filters to an ASP that in turn sends a SELECT based on those parameters the SQL database and we get data back to the program.
Stepped through the code and found the error returns after this line
oSqlServConn.Open "Provider=MSDAOSP;Data Source=MSXML2.DSOControl.2.6"
Any thoughts out in ForumLand? Please take it easy on me since I didn't write most of this code. Just trying to solve the problem. :)Check if this (http://support.microsoft.com/default.aspx?scid=kb;en-us;312288) pertains to your situation.|||Nope. Unfortunately not. Only sending a handful of filters and the user has Service Pack 4 already. Wouldn't be as concerned (since this is a user that rarely needs the data and can get it via other means) except this person has the newest computer on the block.|||Still having this problem. Any thoughts out there?|||Check tables names and columns names in SQL. I think there may be issue in deploying columns referred by the page.
Check the following :
Use client-side cursors (by setting the ADO recordset Cursor Location property to adUseClient).
Remove the insert trigger from the source table.
Put SET NOCOUNT ON line at the beginning of the trigger code.
After calling Update the first time to insert the new row in the table, scroll the recordset using methods like MoveNext and MovePrevious before calling Update again.
HTH|||Setting cursor location may affect the situation, but the rest simply does not apply, - the error occurs at the time of initializing the connection, not at the time of execution of an action query that fires a trigger.|||Tried setting cursor location on either side of the equation and still no go. I can recreate the problem on my computer now as long as I'm pointing to a test SQL server. When I switch over and point to our Production SQL server, I get no error.
Microsoft OLE DB Provider for ODBC Drivers (0x80040E21) Multiple-step OLE DB operation
generated errors. Check each OLE DB status value, if available. No work was done.
This is the only user that is currently getting the message. Last week another user got this one day and then it stopped.
Inside VB6 code, we're sending some filters to an ASP that in turn sends a SELECT based on those parameters the SQL database and we get data back to the program.
Stepped through the code and found the error returns after this line
oSqlServConn.Open "Provider=MSDAOSP;Data Source=MSXML2.DSOControl.2.6"
Any thoughts out in ForumLand? Please take it easy on me since I didn't write most of this code. Just trying to solve the problem. :)Check if this (http://support.microsoft.com/default.aspx?scid=kb;en-us;312288) pertains to your situation.|||Nope. Unfortunately not. Only sending a handful of filters and the user has Service Pack 4 already. Wouldn't be as concerned (since this is a user that rarely needs the data and can get it via other means) except this person has the newest computer on the block.|||Still having this problem. Any thoughts out there?|||Check tables names and columns names in SQL. I think there may be issue in deploying columns referred by the page.
Check the following :
Use client-side cursors (by setting the ADO recordset Cursor Location property to adUseClient).
Remove the insert trigger from the source table.
Put SET NOCOUNT ON line at the beginning of the trigger code.
After calling Update the first time to insert the new row in the table, scroll the recordset using methods like MoveNext and MovePrevious before calling Update again.
HTH|||Setting cursor location may affect the situation, but the rest simply does not apply, - the error occurs at the time of initializing the connection, not at the time of execution of an action query that fires a trigger.|||Tried setting cursor location on either side of the equation and still no go. I can recreate the problem on my computer now as long as I'm pointing to a test SQL server. When I switch over and point to our Production SQL server, I get no error.
Subscribe to:
Posts (Atom)