Showing posts with label state. Show all posts
Showing posts with label state. Show all posts

Friday, March 30, 2012

Help!!!! Restore file mdf after exec "Drop table..." to previous state.

Hi all.
First, sorry about my poor english.

I have a database which above 6 gb data and i have droped all table in my database.
I try to restore from log file but my database is set to simple backup and auto shrink so log file doesn't help anymore.
I have used some software to recovery from log file too but useless.
My only hope right now is mdf file.
Please help me. How could i restore my mdf file to state before i droped tables.
Thanks

Since you are in simple recovery model, you can't use transaction log backups and none of the recovery tools on the market will be able to help since they rely on the contents of the transaction log to get the data back. If you don't have a backup of the database, the data is gone.

|||

There is actually a VERY brute force way that you really aren't going to like. Dropping objects in SQL Server works very similar to deleting a file on the operating system. You don't actually wipe out the file, you just remove an 8 byte header that essentially says "I'm a valid file". In SQL Server, you remove the object from the SQL Server metadata. Once the entries for the object have been removed from sysindexes, SQL Server will no longer find the data. Unless you have done something to reallocate those pages to another object in which case everything will be wiped out on that page, you can actually get to the raw pages. This is NOT pretty. You can use the DBCC PAGE command to read a page. You would wind up running this one page at a time and extracting the data from each page as you go. Then you would have to reconstruct everything and manually reload the data. (Did I mention, you REALLY don't want to have to do this which is why you always take frequent backups.)

So, step 1 in this process is to immediately create a backup of the database. Step 2 is to immediately put a backup plan in place so that the database is being backed up on a routine basis. Then you can use the following set of commands to manually extract the data. Below is an example. You would substitute your database name. You would then start at file = 1 and page = 1 and incrementally walk through page 2, 3, 4, ... and then repeat the process for any other files present in the database. The final step in the process would be to test your backup strategy and continue to test it on a frequent basis. (If you don't keep a backup of a database, you are basically saying that it is unimportant and you don't care about losing it.)

--dbcc page ( {'dbname' | dbid}, filenum, pagenum [, printopt={0|1|2|3} ])

dbcc traceon (3604)

dbcc page (pubs,1,88,3)

go

|||Thanks very much.
As you mentioned, i try to use DBCC PAGE and it has a lot of thing which i don't understand.
Please show me the way to read info from what DBCC Page return and meaning of those.
Thanks again.|||You are reading the raw storage on a page using this command. It is easier to just point you at a book. Go out and pick up a copy of "Inside SQL Server 2000" by Kalen Delaney. There are about 100 pages of material that relate back to interpreting and utilizing the output from DBCC PAGE.|||I will read it and find what i can do with that book.
You help me very much, thanks. :)|||BTW, the DBCC PAGE command is an undocumented command which means it is not supported by Microsoft (but nobody is stopping you from not using them). Try Googling around for some references on these undocumented commands, stored procedures and functions and you will find a lot of useful ones.|||I have read the book which you mentioned. I try to find out exactly what you mean when you said i can read pages in mdf file one by one but i don't get it.
Could you tell me which tools or language or anything else to perform that idea.
Thanks|||

If you query sysfiles within a database, you get the list of FileIDs. In general, if you have an mdf file, it will be fileID = 1.

So you use DBCC page to read each page manually by doing the following:

1. Open a query window.

2. Execute:

DBCC TRACEON(3604)

DBCC PAGE(<database name>,1,1,3)

3. Read the contents of the page and extract any data that you need

4. Execute:

DBCC TRACEON(3604)

DBCC PAGE(<database name>,1,2,3)

5. Read the contents of the page and extract any data that you need

6. Execute:

DBCC TRACEON(3604)

DBCC PAGE(<database name>,1,3,3)

7. Read the contents of the page and extract any data that you need

8. Execute:

DBCC TRACEON(3604)

DBCC PAGE(<database name>,1,4,3)

Etc. There isn't any tool to do this. You do this in Transact-SQL. Like I said when I brought this up, this is an absolute last resort if you can access the database, it is EXTREMELY ugly, EXTREMELY resource intensive, and EXTREMELY time consuming. Why, because you pull page 1, then page 2, then page 3, then page 4, then page 5, then.... until you get an error message that the page doesn't exist. Even in a small database, you can have hundreds or thousands of pages, so that means that in even a small database, you would have to execute DBCC PAGE hundreds or thousands of times, read the contents of the page, and manually extract the data. In production databases, you can easily have millions or billions or pages.

Now you get the idea why everyone jumps up and down about backups and why it would be nice if Microsoft could ship a 100 foot tall poster in the box with SQL Server that has exactly one message on it, backup your databases. If you don't have backups and you need to recover data, there are few, if any options, and you are not going to like ANY of the options.

|||Michael Hotek,
I already exec Dbcc page and i get a lot of things which i don't understand.
So, what do you mean when you said:"Read the contents of the page and extract any data that you need". How to read and extract it? By T-SQL or something else?
About my database, I give up.So, right now,I just want to know more about SQL and the way to extract the contents of the page.
Thanks
|||Copy it from the results window and paste it into Notepad, another Query window etc. This is a 100% manual process. There are zero tools. There are no shortcuts. There is no easy way to do this. In essence you are going to manually type back in every single piece of data within the database. If you go through about 100 pages in your database and look at the results, the data is pretty self-explanatory. Since you are starting at page 1, there are going to be entire pages that you aren't going to be able to do things with such as the PFS page, GAM page, SGAM page, index pages, etc. But, there are data pages in your database and when you hit one, it will be very apparent where the data is and what it means. Other than that, it's up to you. You have to look at the results pane and you have to highlight the data and copy it back out into something else in order to stick it back into your database.|||Michael Hotek
Now, I understand what you mean, thanks. :)sql

Friday, March 23, 2012

HELP! restore database - left in loading state? PLEASE HELP!

Hi all-
I actually don't work in SQL Server administration but I am trying to restore a database. I am a developer. I deleted all the rows from one of the tables in a database and I need to get that particular table back. The people that actually do the restor
e for me tell me that the RESTORE part has completed, but now the database says "(loading)" and stays this way indefinitely! They are trying to restore the database to a temporary location on another server, so that we can then just take the ONE table th
at I need back and import it back over. No one seems to have any idea how to move beyond this "loading" state and access the tables. Does this sound familiar to anyone? Please help - this is production data!!!!!! Thanks so much!!!
Try:
restore database MyDB with recovery
Tom
Thomas A. Moreau, BSc, PhD, MCSE, MCDBA
SQL Server MVP
Columnist, SQL Server Professional
Toronto, ON Canada
www.pinnaclepublishing.com/sql
"KMZ_state" <KMZ_state@.discussions.microsoft.com> wrote in message
news:A9DCF94E-276C-4D74-BB22-D55FCD672461@.microsoft.com...
Hi all-
I actually don't work in SQL Server administration but I am trying to
restore a database. I am a developer. I deleted all the rows from one of
the tables in a database and I need to get that particular table back. The
people that actually do the restore for me tell me that the RESTORE part has
completed, but now the database says "(loading)" and stays this way
indefinitely! They are trying to restore the database to a temporary
location on another server, so that we can then just take the ONE table that
I need back and import it back over. No one seems to have any idea how to
move beyond this "loading" state and access the tables. Does this sound
familiar to anyone? Please help - this is production data!!!!!! Thanks
so much!!!
|||Try:
restore database MyDB with recovery
Tom
Thomas A. Moreau, BSc, PhD, MCSE, MCDBA
SQL Server MVP
Columnist, SQL Server Professional
Toronto, ON Canada
www.pinnaclepublishing.com/sql
"KMZ_state" <KMZ_state@.discussions.microsoft.com> wrote in message
news:A9DCF94E-276C-4D74-BB22-D55FCD672461@.microsoft.com...
Hi all-
I actually don't work in SQL Server administration but I am trying to
restore a database. I am a developer. I deleted all the rows from one of
the tables in a database and I need to get that particular table back. The
people that actually do the restore for me tell me that the RESTORE part has
completed, but now the database says "(loading)" and stays this way
indefinitely! They are trying to restore the database to a temporary
location on another server, so that we can then just take the ONE table that
I need back and import it back over. No one seems to have any idea how to
move beyond this "loading" state and access the tables. Does this sound
familiar to anyone? Please help - this is production data!!!!!! Thanks
so much!!!
sql

Monday, March 12, 2012

Help! Databases are in "Loading" state after Restore from tape!

I run MS SQL Server 2000 (8.00.194) on a Windows 2000 Server.

After having problems with extremely large logfiles, I was told to stop the SQL Service, and delete the logs, and when I restarted the SQL Service the Server would recreate the log files. That did not happend, and the databases had "Suspect" state. After I've tried a few things found on this forum among others, I ended up restoring the db's from my last tape backup.

This was successfully (with Veritas Backup Exec), but now the databases have "Loading" state. I've searched the forums, but haven't found a solution, please help!

Thank you in advance!In Query Analyzer, issue the following command:

restore database yourdatabase with recovery

Substitute your database's name with "yourdatabase".

That should clear up the loading state. I trust you have resolved to never again take advice from the guy that told you to delete the log files?|||Originally posted by MCrowley
In Query Analyzer, issue the following command:

restore database yourdatabase with recovery

Substitute your database's name with "yourdatabase".

That should clear up the loading state. I trust you have resolved to never again take advice from the guy that told you to delete the log files?

Thanks for your answer. I tried it, and got this msg back:

Server: Msg 4331, Level 16, State 1, Line 1
The database cannot be recovered because the files have been restored to inconsistent points in time.
Server: Msg 3013, Level 16, State 1, Line 1
RESTORE DATABASE is terminating abnormally.

:(

Yes, I will not delete them again, but I seriously need to get these databases up and running.|||As you can see, I have full backup of the databases on tape.

So If anyone could give me info on how to do a restore correctly, that will also solve my problem.

Thanks, again.|||here is a link to an article at Veritas that may help you out:

http://seer.support.veritas.com/docs/258895.htm

do you only have the backups done through the Veritas agent? or do you also have files from a SQL Server initiated backup (like from a maintenance plan)? If you have backup files you can restore those to disk and then restore through SQL Server.

It might not help now, but you might want to consider scheduling a backup to disk (either standalone or through a maintenance plan) in addition to your agent backups. I personally don't trust backups that go straight to tape, they're good to have as additional insurance, but I wouldn't rely on them alone.

If you are running 8.00.194 (RTM) you might also want to look into getting that server up to SP3a or at least to a point where you're covered against the various vulnerabilities like slammer, etc.. that is of course if your application will run correctly|||Originally posted by drew
here is a link to an article at Veritas that may help you out:

http://seer.support.veritas.com/docs/258895.htm

do you only have the backups done through the Veritas agent? or do you also have files from a SQL Server initiated backup (like from a maintenance plan)? If you have backup files you can restore those to disk and then restore through SQL Server.

It might not help now, but you might want to consider scheduling a backup to disk (either standalone or through a maintenance plan) in addition to your agent backups. I personally don't trust backups that go straight to tape, they're good to have as additional insurance, but I wouldn't rely on them alone.

If you are running 8.00.194 (RTM) you might also want to look into getting that server up to SP3a or at least to a point where you're covered against the various vulnerabilities like slammer, etc.. that is of course if your application will run correctly

Thanks for your answer, I'll look into what the article describes. I've understand that this backup isn't good enought, sp it will be changed as soon as I have my data up and running again. About the upgrade, it has not been done due to compatibility problems. Hopefully it will soon be patched with latest sp.|||You can try this code to force your database out of the loading state, but because it modifies system tables use it at your own risk:

sp_configure 'allow updates', 1
RECONFIGURE WITH OVERRIDE
go
update master..sysdatabases
set status = status - 32
where name = 'YourDatabaseName' and status & 32 > 0
go
sp_configure 'allow updates', 0
RECONFIGURE WITH OVERRIDE
go

If this does not work, try dropping and recreating your databases prior to running MCrowley's RESTORE DATABASE suggestion.

blindman|||Seems like the veritas article was what I needed to at least get the first backup database back :D

Thanks a lot everyone...one db to go, hopefully that's goes okay as well.

This forum is awesome. Helping a n00b who started with sql a few hours ago, thanks again!

- Everything is back and up and running from the backup.
Good night ppl!

Wednesday, March 7, 2012

help!

sql2k sp3
I accidentally started restoreing the wrong db. I
cancelled it and now its in a load state. Can I just put
it back!!!
Your only recourse to restore from your latest database backup.
Hope this helps.
Dan Guzman
SQL Server MVP
"ChrisR" <anonymous@.discussions.microsoft.com> wrote in message
news:43fa01c47ff4$26cc0870$a301280a@.phx.gbl...
> sql2k sp3
> I accidentally started restoreing the wrong db. I
> cancelled it and now its in a load state. Can I just put
> it back!!!

Monday, February 27, 2012

help!

sql2k sp3
I accidentally started restoreing the wrong db. I
cancelled it and now its in a load state. Can I just put
it back!!!Your only recourse to restore from your latest database backup.
Hope this helps.
Dan Guzman
SQL Server MVP
"ChrisR" <anonymous@.discussions.microsoft.com> wrote in message
news:43fa01c47ff4$26cc0870$a301280a@.phx.gbl...
> sql2k sp3
> I accidentally started restoreing the wrong db. I
> cancelled it and now its in a load state. Can I just put
> it back!!!

help!

sql2k sp3
I accidentally started restoreing the wrong db. I
cancelled it and now its in a load state. Can I just put
it back!!!>--Original Message--
>sql2k sp3
>I accidentally started restoreing the wrong db. I
>cancelled it and now its in a load state. Can I just put
>it back!!!
>.
>|||Your only recourse to restore from your latest database backup.
--
Hope this helps.
Dan Guzman
SQL Server MVP
"ChrisR" <anonymous@.discussions.microsoft.com> wrote in message
news:43fa01c47ff4$26cc0870$a301280a@.phx.gbl...
> sql2k sp3
> I accidentally started restoreing the wrong db. I
> cancelled it and now its in a load state. Can I just put
> it back!!!

Friday, February 24, 2012

Help with xp_sendmail needed!

Hello,
I am using xp_sendmail SP to send emails to myself, not to a distribution li
st. I receive the error: Server: Msg 18031, Level 16, State 1, Line 0
xp_sendmail: Could not resolve recipient
The server is a MS Windows 2003 running SQL 2000 and Office XP SP3. The OS,
SQL and Office are fully updated. I do not think that this problem is relate
d to the bug described in Article ID:315666.
May I ask you for some help?
Thank you,
Ovidiu TanjalaHi Ovidiu,
Are you able to execute xp_stopmail and xp_startmail successfully? Also
please post your xp_sendmail statement, which resulted in this error.
Thanks
Yogish

Help with xp_sendmail needed!

Hello,
I am using xp_sendmail SP to send emails to myself, not to a distribution list. I receive the error: Server: Msg 18031, Level 16, State 1, Line 0
xp_sendmail: Could not resolve recipient
The server is a MS Windows 2003 running SQL 2000 and Office XP SP3. The OS, SQL and Office are fully updated. I do not think that this problem is related to the bug described in Article ID:315666.
May I ask you for some help?
Thank you,
Ovidiu Tanjala
Hi Ovidiu,
Are you able to execute xp_stopmail and xp_startmail successfully? Also
please post your xp_sendmail statement, which resulted in this error.
Thanks
Yogish

Help with xp..sendmail needed!

Hi,
I keep getting the following error in my SP which I can't seem to resolve:-
Server: Msg 18031, Level 16, State 1, Line 0
xp_sendmail: Could not resolve recipient
If anyone has any ideas why this is happening it would be greatly
appreciated. My SP is below for reference.
DECLARE @.REG_NO as varchar(10)
DECLARE @.URN as varchar(10)
DECLARE @.OFFICER as varchar(10)
DECLARE @.RENEWAL_DATE as varchar(10)
DECLARE @.OFFICER_EMAIL as varchar(15)
DECLARE @.sbj as varchar(50)
DECLARE @.msg as varchar(50)
DECLARE @.recipient as varchar(50)
DECLARE surveillance_cursor CURSOR FAST_FORWARD FOR
SELECT
REG_NO = s.s_id,
URN = d.sd_urn,
OFFICER = d.sd_reviewing_officer,
RENEWAL_DATE = CONVERT(VARCHAR,d.sd_renewal_date, 103),
OFFICER_EMAIL = e.e_officer_email
FROM
dbo.tbl_surveillance s
INNER JOIN
dbo.tbl_surveillance_dates d
ON
s.s_id = d.sd_s_id
LEFT OUTER JOIN
dbo.tbl_email e
ON
d.sd_e_id = e.e_id
WHERE
d.sd_renewal_date < GETDATE()+7;
OPEN surveillance_cursor
-- Perform the first fetch and store the values in variables.
-- Note: The variables should be in the same order as the columns in the
--SELECT statement.
FETCH NEXT FROM surveillance_cursor
INTO @.REG_NO, @.URN, @.OFFICER, @.RENEWAL_DATE, @.OFFICER_EMAIL
-- Check @.@.FETCH_STATUS to see if there are any more rows to fetch.
WHILE @.@.FETCH_STATUS = 0
BEGIN
select @.recipient = @.OFFICER_EMAIL
select @.sbj = 'List of Renewal Dates'
select @.msg = @.REG_NO + ', ' + @.URN + ', ' + @.OFFICER + ',' + @.RENEWAL_DATE
exec master..xp_sendmail @.recipients= @.recipient, @.subject = @.sbj,
@.message=@.msg
-- This is executed as long as the previous fetch succeeds.
FETCH NEXT FROM surveillance_cursor
INTO @.REG_NO, @.URN, @.OFFICER, @.RENEWAL_DATE, @.OFFICER_EMAIL
END
CLOSE surveillance_cursor
DEALLOCATE surveillance_cursor
GO
Really appreciate any help on this.
Thanks
DamonDoes xp_sendmail work if you call it manually (e.g. not populating the
elements with variables)? If you can't get xp_sendmail to work at all, you
might save time by reading http://www.aspfaq.com/2403 and using an
alternative. If you are using SQL Server 2005, you should consider database
mail instead (sorry, the article hasn't been updated for that).
Did you try wrapping the call in
IF @.OFFICER_EMAIL IS NOT NULL
BEGIN
..
END
Or better yet, have an e-mail format checking function,
IF dbo.IsEmail(@.OFFICER_EMAIL)
BEGIN
..
END
xp_sendmail also seems to be fussy about trailing spaces, and while they
shouldn't be there because it is varchar, you could try:
SET @.OFFICER_EMAIL = LTRIM(RTRIM(@.OFFICER_EMAIL))
Finally, if @.OFFICER_EMAIL is a distribution list, see
http://support.microsoft.com/kb/315666
"Damon" <nonsense@.nononsense.com> wrote in message
news:2oQsf.18319$mn1.4396@.newsfe7-win.ntli.net...
> Hi,
> I keep getting the following error in my SP which I can't seem to
> resolve:-
> Server: Msg 18031, Level 16, State 1, Line 0
> xp_sendmail: Could not resolve recipient
> If anyone has any ideas why this is happening it would be greatly
> appreciated. My SP is below for reference.
> DECLARE @.REG_NO as varchar(10)
> DECLARE @.URN as varchar(10)
> DECLARE @.OFFICER as varchar(10)
> DECLARE @.RENEWAL_DATE as varchar(10)
> DECLARE @.OFFICER_EMAIL as varchar(15)
> DECLARE @.sbj as varchar(50)
> DECLARE @.msg as varchar(50)
> DECLARE @.recipient as varchar(50)
> DECLARE surveillance_cursor CURSOR FAST_FORWARD FOR
> SELECT
> REG_NO = s.s_id,
> URN = d.sd_urn,
> OFFICER = d.sd_reviewing_officer,
> RENEWAL_DATE = CONVERT(VARCHAR,d.sd_renewal_date, 103),
> OFFICER_EMAIL = e.e_officer_email
> FROM
> dbo.tbl_surveillance s
> INNER JOIN
> dbo.tbl_surveillance_dates d
> ON
> s.s_id = d.sd_s_id
> LEFT OUTER JOIN
> dbo.tbl_email e
> ON
> d.sd_e_id = e.e_id
> WHERE
> d.sd_renewal_date < GETDATE()+7;
> OPEN surveillance_cursor
> -- Perform the first fetch and store the values in variables.
> -- Note: The variables should be in the same order as the columns in the
> --SELECT statement.
> FETCH NEXT FROM surveillance_cursor
> INTO @.REG_NO, @.URN, @.OFFICER, @.RENEWAL_DATE, @.OFFICER_EMAIL
> -- Check @.@.FETCH_STATUS to see if there are any more rows to fetch.
> WHILE @.@.FETCH_STATUS = 0
> BEGIN
> select @.recipient = @.OFFICER_EMAIL
> select @.sbj = 'List of Renewal Dates'
> select @.msg = @.REG_NO + ', ' + @.URN + ', ' + @.OFFICER + ',' +
> @.RENEWAL_DATE
> exec master..xp_sendmail @.recipients= @.recipient, @.subject = @.sbj,
> @.message=@.msg
> -- This is executed as long as the previous fetch succeeds.
> FETCH NEXT FROM surveillance_cursor
> INTO @.REG_NO, @.URN, @.OFFICER, @.RENEWAL_DATE, @.OFFICER_EMAIL
> END
> CLOSE surveillance_cursor
> DEALLOCATE surveillance_cursor
> GO
>
>
> Really appreciate any help on this.
> Thanks
> Damon
>|||hi,
Thank you very much for your response. I have tried xp_sendmail manually by
typing it into Query Analyzer and it works fine. It doesn't seem to like it
in my SP.
I have also added the IF @.OFFICER_EMAIL IS NOT NULL and SET @.OFFICER_EMAIL =
LTRIM(RTRIM(@.OFFICER_EMAIL)) into my Stored Procedure but I still get the
same error.
Any more advice is greatly appreciated.
Thanks
Damon
"Aaron Bertrand [SQL Server MVP]" <ten.xoc@.dnartreb.noraa> wrote in message
news:e2vgJxHDGHA.528@.TK2MSFTNGP09.phx.gbl...
> Does xp_sendmail work if you call it manually (e.g. not populating the
> elements with variables)? If you can't get xp_sendmail to work at all,
> you might save time by reading http://www.aspfaq.com/2403 and using an
> alternative. If you are using SQL Server 2005, you should consider
> database mail instead (sorry, the article hasn't been updated for that).
> Did you try wrapping the call in
> IF @.OFFICER_EMAIL IS NOT NULL
> BEGIN
> ...
> END
> Or better yet, have an e-mail format checking function,
> IF dbo.IsEmail(@.OFFICER_EMAIL)
> BEGIN
> ...
> END
> xp_sendmail also seems to be fussy about trailing spaces, and while they
> shouldn't be there because it is varchar, you could try:
> SET @.OFFICER_EMAIL = LTRIM(RTRIM(@.OFFICER_EMAIL))
> Finally, if @.OFFICER_EMAIL is a distribution list, see
> http://support.microsoft.com/kb/315666
>
>
> "Damon" <nonsense@.nononsense.com> wrote in message
> news:2oQsf.18319$mn1.4396@.newsfe7-win.ntli.net...
>|||> Any more advice is greatly appreciated.

> DECLARE @.OFFICER_EMAIL as varchar(15)
Well, is it remotely possible that any of your e-mail addresses are longer
than 15 characters? What is the table structure of tbl_email? What is
the datatype of e_officer_email?|||Do you know what; I think I just made a complete rookie mistake. It was the
DECLARE @.OFFICER_EMAIL as varchar(15). It should have been 30.
I cannot thank you enough.
Damon
"Aaron Bertrand [SQL Server MVP]" <ten.xoc@.dnartreb.noraa> wrote in message
news:eFP6phIDGHA.1312@.TK2MSFTNGP09.phx.gbl...
>
> Well, is it remotely possible that any of your e-mail addresses are longer
> than 15 characters? What is the table structure of tbl_email? What is
> the datatype of e_officer_email?
>|||> Do you know what; I think I just made a complete rookie mistake. It was
> the DECLARE @.OFFICER_EMAIL as varchar(15). It should have been 30.
Our systems use VARCHAR(128). Even I have e-mail addresses that are > 30
characters, and I don't have an abnormally long name or domain names...|||Good idea, I think I will chane it to that.
Thanks again for your help.
"Aaron Bertrand [SQL Server MVP]" <ten.xoc@.dnartreb.noraa> wrote in message
news:uXyqv1IDGHA.208@.TK2MSFTNGP10.phx.gbl...
> Our systems use VARCHAR(128). Even I have e-mail addresses that are > 30
> characters, and I don't have an abnormally long name or domain names...
>

Sunday, February 19, 2012

Help with UDF using OPENROWSET to EXECUTE sproc

Here is the UDF I am trying to create:
ALTER FUNCTION dbo.TieredAccessCounties
(
@.State CHAR(2)
, @.SourceTable CHAR(1)
, @.UserName VARCHAR(30)
)
RETURNS TABLE
AS
RETURN
SELECT A.* FROM
OPENROWSET('SQLOLEDB','MDWDATA';'sa';'pa
sswordX',
'EXECUTE dbo.AccountFetchCounties NULL, @.SourceTable, @.UserName ')
AS A
I cannot get this to work. I am getting these messages:
Server: Msg 8180, Level 16, State 1, Procedure TieredAccessCounties,
Line 10
Statement(s) could not be prepared.
Server: Msg 137, Level 15, State 1, Procedure TieredAccessCounties,
Line 10
Must declare the variable '@.SourceTable'.
[OLE/DB provider returned message: Deferred prepare could not be
completed.]OPENROWSET is opening the connection to MDWDATA and executing the following
(literally):
'EXECUTE dbo.AccountFetchCounties NULL, @.SourceTable, @.UserName '
It has no idea what @.SourceTable and @.UserName are. Unfortunately, there's
no way I know of to pass values into OPENROWSET within a UDF.
Can you describe what you're trying to do? Maybe there's a better way than
using a UDF.
Adam Machanic
SQL Server MVP
http://www.sqljunkies.com/weblog/amachanic
--
"JJA" <johna@.cbmiweb.com> wrote in message
news:1104430908.817837.179350@.z14g2000cwz.googlegroups.com...
> Here is the UDF I am trying to create:
> ALTER FUNCTION dbo.TieredAccessCounties
> (
> @.State CHAR(2)
> , @.SourceTable CHAR(1)
> , @.UserName VARCHAR(30)
> )
> RETURNS TABLE
> AS
> RETURN
> SELECT A.* FROM
> OPENROWSET('SQLOLEDB','MDWDATA';'sa';'pa
sswordX',
> 'EXECUTE dbo.AccountFetchCounties NULL, @.SourceTable, @.UserName ')
> AS A
> I cannot get this to work. I am getting these messages:
> Server: Msg 8180, Level 16, State 1, Procedure TieredAccessCounties,
> Line 10
> Statement(s) could not be prepared.
> Server: Msg 137, Level 15, State 1, Procedure TieredAccessCounties,
> Line 10
> Must declare the variable '@.SourceTable'.
> [OLE/DB provider returned message: Deferred prepare could not be
> completed.]
>|||The sproc dbo.AccountFetchCounties is a bit of business logic that
takes 3 parms and returns a set of rows representing state-county areas
that are "allowed" for a given username. I need to add this
functionality inside of a much larger stored procedure and I need to
JOIN the output of this sproc with another SELECT. The first problem I
ran into was that I got the message: INSERT EXEC CANNOT BE NESTED
because I had created a temp table to hold the rows back from
AccountFetchCounties (but this in turn was inside of an outer INSERT
into tableX EXECUTE myOuterSproc structure.
So that is why I thought to use User Defined Function to return a
table. But then I see that a UDF cannot call a stored procedure. So I
researched and discovered OPENROWSET as an alternative. But now I am
stuck with this strange message. I really appreciate your help. Thank
you for your quick reply.|||Can you post some code to duplicate the CANNOT BE NESTED error? I've never
seen it before, and was just about to recommend a temp table. There must be
a way around that...
Adam Machanic
SQL Server MVP
http://www.sqljunkies.com/weblog/amachanic
--
"JJA" <johna@.cbmiweb.com> wrote in message
news:1104433457.065710.65650@.z14g2000cwz.googlegroups.com...
> The sproc dbo.AccountFetchCounties is a bit of business logic that
> takes 3 parms and returns a set of rows representing state-county areas
> that are "allowed" for a given username. I need to add this
> functionality inside of a much larger stored procedure and I need to
> JOIN the output of this sproc with another SELECT. The first problem I
> ran into was that I got the message: INSERT EXEC CANNOT BE NESTED
> because I had created a temp table to hold the rows back from
> AccountFetchCounties (but this in turn was inside of an outer INSERT
> into tableX EXECUTE myOuterSproc structure.
> So that is why I thought to use User Defined Function to return a
> table. But then I see that a UDF cannot call a stored procedure. So I
> researched and discovered OPENROWSET as an alternative. But now I am
> stuck with this strange message. I really appreciate your help. Thank
> you for your quick reply.
>|||Adam,
Here's an example:
create table T (
i int
)
go
create proc p as select 4
go
create proc q as
insert into T exec p
go
insert into T exec q
go
drop proc p,q
drop table T
I believe EXEC can be nested, and it's just INSERT .. EXEC that can't be
nested. In other words, the statement INSERT INTO T EXEC q will fail
if the procedure q contains an INSERT .. EXEC construction.
SK
Adam Machanic wrote:

>Can you post some code to duplicate the CANNOT BE NESTED error? I've never
>seen it before, and was just about to recommend a temp table. There must b
e
>a way around that...
>
>|||"Steve Kass" <skass@.drew.edu> wrote in message
news:uU38dyu7EHA.2196@.TK2MSFTNGP14.phx.gbl...
> I believe EXEC can be nested, and it's just INSERT .. EXEC that can't be
> nested. In other words, the statement INSERT INTO T EXEC q will fail
> if the procedure q contains an INSERT .. EXEC construction.
That makes perfect sense. The example you posted doesn't seem to do
anything, whereas at least something like this has some semblance of
purpose:
EXEC ('EXEC (''SELECT 1'')')
.. not that I'd do that, but at least it makes more sense than nesting
an INSERT
Adam Machanic
SQL Server MVP
http://www.sqljunkies.com/weblog/amachanic
--|||-- here is the 1st fragment, inside of a large production sproc. It
needs to create and populate #Areas which
-- will be used in JOINS later in the sproc and in the inner sprocs it
calls.
create table #areas
(
state char(2) ,
county char(3)
, SMSA_CD varchar(10) )
Execute dbo.AMS_I_GetAreasV2 -- 12/29/2004 JJA: add
parm for tiered-access support of custom areas using
dbo.AMS_I_GetAreasV2
@.SMSA,
@.S1,
@.C1,
@.SourceTable
, @.CustomID = @.CustomID -- 09/20/2004 JJA: Add support for Custom
Area Definitions as a source for populating #Areas table
, @.UserName = @.UserName -- 12/29/2004 JJA: Make Custom Area
Definitions conform to tiered access rules and limits
-- here is the 2nd fragment (EXECUTEd from above):
ALTER Procedure dbo.AMS_I_GetAreasV2
(
@.SMSA VarChar(10) = NULL,
@.S1 Char(2) = NULL,
@.C1 Char(3) = NULL,
@.SourceTable varchar(1) = 'P' -- P: Purchase-Money R: Refi B:
Both F: FHA V: VA G: All_Govt
, @.CustomID INT = 0 -- 09/20/2004 JJA; 12/09/2004 JJA
, @.Debug int = 0 -- 03/01/2004 JJA
)
As
Set NOCount ON
declare @.err int, @.rows int -- 03/01/2004 JJA - capture essentials for
debugging
declare @.sepid varchar(80)
declare @.time varchar(30)
select @.sepid = ' - AMS_I_GetAreasV2: '
DECLARE @.SMSAV VARCHAR(10)
SELECT @.SMSAV = RTRIM(@.SMSA)
If @.SMSAV IS NULL
begin
SELECT @.SMSAV = ''; -- this will enable PRINT below to occur and
DATALENGTH(@.SMSAV) to be 0 so CASE logic below works
end
select @.time = convert(varchar(30), getdate(), 109)
print @.time + @.sepid + ' entered. SMSA = ' + @.SMSAV + '; SourceTable =
' + @.SourceTable + '; CustomID = ' + Convert(Varchar(9),@.CustomID)
if @.CustomID > 0 -- In this mode, a custom area definition is
translated -- 09/20/2004 JJA
BEGIN -- 09/20/2004 JJA
print @.time + @.sepid + ' Custom-Area Definition Mode is in
effect.' -- 09/20/2004 JJA
INSERT INTO #Areas -- 09/20/2004 JJA
EXECUTE @.ERR = dbo.AMS_I_GetAreasV2_CustomAreaTranslator @.CustomID --
09/20/2004 JJA
,@.Debug -- 09/20/2004 JJA
-- , @.SourceTable, @.UserName
-- I had to abandon these new arguments when nesting complaint
showed up
SELECT @.ROWS = @.@.ROWCOUNT -- 09/20/2004 JJA
GOTO CommonExitPoint -- 09/20/2004 JJA
END
--SMSA:
IF datalength(@.SMSAV) = 4 --SMSA
BEGIN
print @.time + @.sepid + ' SMSA Mode in effect.'
If @.SourceTable = 'P'
Begin
INSERT INTO #Areas
SELECT C.State_cd, C.County_Cd, @.SMSAV AS SMSA_CD
FROM County C INNER JOIN SMSA M ON C.SMSA_CD = M.SMSA_CD
WHERE C.SMSA_CD = @.SMSAV AND C.PDATA = 'YES'
.........etc. etc.
----
--
ALTER procedure dbo.AMS_I_GetAreasV2_CustomAreaTranslator
----
--*
-- PURPOSE: Translate an ID for a custom area into a record set of
-- areas that the custom area defines. If any metro-area is part
-- of a custom-area definition, its component STATE and COUNTY are
-- included in this record set (otherwise SMSA is left as NULL).
-- USAGE: Called by AMS_I_GetAreasV2 to populate #Areas
-- HISTORY: 09/23/2004 JJA - implement new sproc
----
--*
-- EXECUTE dbo.AMS_I_GetAreasV2_CustomAreaTranslator 1,@.Debug=1
(
@.CustomID int -- key to parent table (i.e. has name of this
definition, etc.)
,@.Debug int = 0 -- set default to 1 for Query-Analyzer debugging
-- ,@.SourceTable char(1)
-- ,@.UserName varchar(30)
)
as
DECLARE @.err int
DECLARE @.rows int
DECLARE @.pid varchar(100)
SELECT @.pid = 'AMS_I_GetAreasV2_CustomAreaTranslator: '
SET NOCOUNT ON
if @.Debug = 1 PRINT @.pid + ' entered for CustomID = ' +
CONVERT(VARCHAR(9),@.CustomID)
-- Here, I tried to do:
Create Table #AllowedCounties
(
County_CD CHAR(3),
TypeCounty VARCHAR(60),
State_CD CHAR(2)
)
INSERT INTO #AllowedCounties
EXECUTE dbo.AccountFetchCounties (NULL, @.CategoryCode = @.SourceTable,
@.UserName = @.UserName)
-- SourceTable and Username would have been passed in from callers.
-- Upon successful creation of temporary table #AllowedCounties, it
would have been added to the
-- SELECT just below as another table to JOIN.
-- Yet the INSERT INTO / EXECUTE construct here is disallowed because
at the top #AREAS is being
-- populated and I got the complaint about nesting immediately
trying to compile this "inner" sproc.
SELECT DISTINCT
C.State_CD
, C.County_CD
, SMSA_CD =
CASE
When Datalength(X.SMSACBSA) = 10 AND X.SMSACBSA = C.CBSACode +
C.CBSADivision Then C.CBSACode + C.CBSADivision
When Datalength(X.SMSACBSA) = 5 AND X.SMSACBSA = C.CBSACode
Then C.CBSACode
When Datalength(X.SMSACBSA) = 4 AND X.SMSACBSA = C.SMSA_CD
Then C.SMSA_CD
END
FROM dbo.AcctCustomArea X
, dbo.GovtCountiesList C
WHERE
X.CustomID = @.CustomID
AND
CASE
When Datalength(X.SMSACBSA) = 10 AND X.SMSACBSA = C.CBSACode +
C.CBSADivision Then 1
When Datalength(X.SMSACBSA) = 5 AND X.SMSACBSA = C.CBSACode
Then 1
When Datalength(X.SMSACBSA) = 4 AND X.SMSACBSA = C.SMSA_CD
Then 1
When X.SMSACBSA IS NULL AND X.State = C.State_CD
AND X.County = C.County_CD Then 1
ELSE 0 -- where 0 = 1 rejects record
END = 1 -- where 1 = 1 allows record
ORDER BY
C.State_CD
, C.County_CD|||I am sorry I did not chop off all comments from the code posted above
(it is pretty hard to read). I will try to summarize:
In this problem, there are 2 pieces of business logic implemented by
stored procedures and called in numerous places by other stored
procedures.
AMS_I_GetAreasV2 is called to populate a temporary table #AREAS which
is used in JOINS here and is used in reporting elsewhere.
AccountFetchCounties is called to return a set of allowed counties
based on a code and username.
In short, I need to expand the functionality of AMS_I_GetAreasV2 such
that in some cases it calls AccountFetchCounties, joining the allowed
set of rows produced by that sproc with another SELECT.
As I said, when I ran into the complaint about nesting, I tried making
a UDF to EXECUTE AccountFetchCounties but that is disallowed. Then I
tried OPENROWSET with EXECUTE of AccountFetchCounties but that does not
allow parameters to be passed to the sproc. Then I posted the original
question.
To solve this in a semi-ugly way, I have replicated all the
functionality of my sproc, AccountFetchCounties, into a UDF. Then in
the SELECT inside 'AMS_I_GetAreasV2_CustomAreaTranslator',
I have
added this UDF which returns a table to my JOIN which works pretty
well.
But I am uncomfortable with the idea of cloning this "business logic"
from SPROC to UDF because of keeping my sanity in the future
maintenance of this code. Thanks in advance for trying to follow my
story and help.|||Here is a better post of code (now cleaned up and fewer comments) that
caused the original nesting error:
-- this CREATE is inside a large production sproc
-- here is the first relevant fragment:
create table #areas
(
state char(2)
, county char(3)
, SMSA_CD varchar(10)
)
Execute dbo.AMS_I_GetAreasV2
@.SMSA,
@.S1,
@.C1,
@.SourceTable
, @.CustomID = @.CustomID
, @.UserName = @.UserName
-- here is the 2nd fragment (EXECUTEd from above):
ALTER Procedure dbo.AMS_I_GetAreasV2
(
@.SMSA VarChar(10) = NULL,
@.S1 Char(2) = NULL,
@.C1 Char(3) = NULL,
@.SourceTable varchar(1) = 'P'
, @.CustomID INT = 0
, @.Debug int = 0
)
As
Set NOCount ON
declare @.err int, @.rows int
DECLARE @.SMSAV VARCHAR(10)
SELECT @.SMSAV = RTRIM(@.SMSA)
If @.SMSAV IS NULL
begin
SELECT @.SMSAV = '';
end
if @.CustomID > 0
BEGIN
INSERT INTO #Areas
EXECUTE @.ERR = dbo.AMS_I_GetAreasV2_CustomAreaTranslator
@.CustomID
,@.Debug
-- , @.SourceTable
-- , @.UserName
-- I had to abandon these new arguments when nesting complaint
-- showed up
SELECT @.ROWS = @.@.ROWCOUNT
GOTO CommonExitPoint
END
--SMSA:
IF datalength(@.SMSAV) = 4
BEGIN
If @.SourceTable = 'P'
Begin
INSERT INTO #Areas
SELECT C.State_cd, C.County_Cd, @.SMSAV AS SMSA_CD
FROM County C INNER JOIN SMSA M ON C.SMSA_CD = M.SMSA_CD
WHERE C.SMSA_CD = @.SMSAV AND C.PDATA = 'YES'
.........etc. etc.
-- here is the 3rd fragment EXECUTED from just above
ALTER procedure dbo.AMS_I_GetAreasV2_CustomAreaTranslator
(
@.CustomID int
,@.Debug int = 0
-- ,@.SourceTable char(1)
-- ,@.UserName varchar(30)
)
as
DECLARE @.err int
DECLARE @.rows int
SET NOCOUNT ON
-- Here, I tried to do:
Create Table #AllowedCounties
(
County_CD CHAR(3),
TypeCounty VARCHAR(60),
State_CD CHAR(2)
)
INSERT INTO #AllowedCounties
EXECUTE dbo.AccountFetchCounties
NULL
, @.CategoryCode = @.SourceTable
, @.UserName = @.UserName
-- SourceTable and Username would have been passed in from callers.
-- Upon successful creation of temporary table #AllowedCounties, it
-- would have been added to the SELECT just below as another table to
JOIN.
-- Yet the INSERT INTO / EXECUTE construct here is disallowed because
-- at the top #AREAS is being populated and I got the complaint about
-- nesting immediately trying to compile this "inner" sproc.
SELECT DISTINCT
C.State_CD
, C.County_CD
, SMSA_CD =
CASE
When Datalength(X.SMSACBSA) = 10 AND X.SMSACBSA = C.CBSACode +
C.CBSADivision Then C.CBSACode + C.CBSADivision
When Datalength(X.SMSACBSA) = 5 AND X.SMSACBSA = C.CBSACode
Then C.CBSACode
When Datalength(X.SMSACBSA) = 4 AND X.SMSACBSA = C.SMSA_CD
Then C.SMSA_CD
END
FROM dbo.AcctCustomArea X
, dbo.GovtCountiesList C
WHERE
X.CustomID = @.CustomID
AND
CASE
When Datalength(X.SMSACBSA) = 10 AND X.SMSACBSA = C.CBSACode +
C.CBSADivision Then 1
When Datalength(X.SMSACBSA) = 5 AND X.SMSACBSA = C.CBSACode
Then 1
When Datalength(X.SMSACBSA) = 4 AND X.SMSACBSA = C.SMSA_CD
Then 1
When X.SMSACBSA IS NULL AND X.State = C.State_CD
AND X.County = C.County_CD Then 1
ELSE 0 -- where 0 = 1 rejects record
END = 1 -- where 1 = 1 allows record
ORDER BY
C.State_CD
, C.County_CD|||Please reply if you can get a chance. I tried to describe my problem
better - maybe I gave too much detail. Bottom line is that I had to
clone business logic of a stored procedure into a user defined
function. I do not like having to do this but it works. Like I said, in
trying to extend the processing of the stored procedure, I ran into
multiple restrictions which I have tried to describe.

Help with UDF using OPENROWSET to EXECUTE sproc

Here is the UDF I am trying to create:
ALTER FUNCTION dbo.TieredAccessCounties
(
@.State CHAR(2)
, @.SourceTable CHAR(1)
, @.UserName VARCHAR(30)
)
RETURNS TABLE
AS
RETURN
SELECT A.* FROM
OPENROWSET('SQLOLEDB','MDWDATA';'sa';'passwordX',
'EXECUTE dbo.AccountFetchCounties NULL, @.SourceTable, @.UserName ')
AS A
I cannot get this to work. I am getting these messages:
Server: Msg 8180, Level 16, State 1, Procedure TieredAccessCounties,
Line 10
Statement(s) could not be prepared.
Server: Msg 137, Level 15, State 1, Procedure TieredAccessCounties,
Line 10
Must declare the variable '@.SourceTable'.
[OLE/DB provider returned message: Deferred prepare could not be
completed.]OPENROWSET is opening the connection to MDWDATA and executing the following
(literally):
'EXECUTE dbo.AccountFetchCounties NULL, @.SourceTable, @.UserName '
It has no idea what @.SourceTable and @.UserName are. Unfortunately, there's
no way I know of to pass values into OPENROWSET within a UDF.
Can you describe what you're trying to do? Maybe there's a better way than
using a UDF.
--
Adam Machanic
SQL Server MVP
http://www.sqljunkies.com/weblog/amachanic
--
"JJA" <johna@.cbmiweb.com> wrote in message
news:1104430908.817837.179350@.z14g2000cwz.googlegroups.com...
> Here is the UDF I am trying to create:
> ALTER FUNCTION dbo.TieredAccessCounties
> (
> @.State CHAR(2)
> , @.SourceTable CHAR(1)
> , @.UserName VARCHAR(30)
> )
> RETURNS TABLE
> AS
> RETURN
> SELECT A.* FROM
> OPENROWSET('SQLOLEDB','MDWDATA';'sa';'passwordX',
> 'EXECUTE dbo.AccountFetchCounties NULL, @.SourceTable, @.UserName ')
> AS A
> I cannot get this to work. I am getting these messages:
> Server: Msg 8180, Level 16, State 1, Procedure TieredAccessCounties,
> Line 10
> Statement(s) could not be prepared.
> Server: Msg 137, Level 15, State 1, Procedure TieredAccessCounties,
> Line 10
> Must declare the variable '@.SourceTable'.
> [OLE/DB provider returned message: Deferred prepare could not be
> completed.]
>|||The sproc dbo.AccountFetchCounties is a bit of business logic that
takes 3 parms and returns a set of rows representing state-county areas
that are "allowed" for a given username. I need to add this
functionality inside of a much larger stored procedure and I need to
JOIN the output of this sproc with another SELECT. The first problem I
ran into was that I got the message: INSERT EXEC CANNOT BE NESTED
because I had created a temp table to hold the rows back from
AccountFetchCounties (but this in turn was inside of an outer INSERT
into tableX EXECUTE myOuterSproc structure.
So that is why I thought to use User Defined Function to return a
table. But then I see that a UDF cannot call a stored procedure. So I
researched and discovered OPENROWSET as an alternative. But now I am
stuck with this strange message. I really appreciate your help. Thank
you for your quick reply.|||Can you post some code to duplicate the CANNOT BE NESTED error? I've never
seen it before, and was just about to recommend a temp table. There must be
a way around that...
--
Adam Machanic
SQL Server MVP
http://www.sqljunkies.com/weblog/amachanic
--
"JJA" <johna@.cbmiweb.com> wrote in message
news:1104433457.065710.65650@.z14g2000cwz.googlegroups.com...
> The sproc dbo.AccountFetchCounties is a bit of business logic that
> takes 3 parms and returns a set of rows representing state-county areas
> that are "allowed" for a given username. I need to add this
> functionality inside of a much larger stored procedure and I need to
> JOIN the output of this sproc with another SELECT. The first problem I
> ran into was that I got the message: INSERT EXEC CANNOT BE NESTED
> because I had created a temp table to hold the rows back from
> AccountFetchCounties (but this in turn was inside of an outer INSERT
> into tableX EXECUTE myOuterSproc structure.
> So that is why I thought to use User Defined Function to return a
> table. But then I see that a UDF cannot call a stored procedure. So I
> researched and discovered OPENROWSET as an alternative. But now I am
> stuck with this strange message. I really appreciate your help. Thank
> you for your quick reply.
>|||Adam,
Here's an example:
create table T (
i int
)
go
create proc p as select 4
go
create proc q as
insert into T exec p
go
insert into T exec q
go
drop proc p,q
drop table T
I believe EXEC can be nested, and it's just INSERT .. EXEC that can't be
nested. In other words, the statement INSERT INTO T EXEC q will fail
if the procedure q contains an INSERT .. EXEC construction.
SK
Adam Machanic wrote:
>Can you post some code to duplicate the CANNOT BE NESTED error? I've never
>seen it before, and was just about to recommend a temp table. There must be
>a way around that...
>
>|||"Steve Kass" <skass@.drew.edu> wrote in message
news:uU38dyu7EHA.2196@.TK2MSFTNGP14.phx.gbl...
> I believe EXEC can be nested, and it's just INSERT .. EXEC that can't be
> nested. In other words, the statement INSERT INTO T EXEC q will fail
> if the procedure q contains an INSERT .. EXEC construction.
That makes perfect sense. The example you posted doesn't seem to do
anything, whereas at least something like this has some semblance of
purpose:
EXEC ('EXEC (''SELECT 1'')')
... not that I'd do that, but at least it makes more sense than nesting
an INSERT :)
--
Adam Machanic
SQL Server MVP
http://www.sqljunkies.com/weblog/amachanic
--|||-- here is the 1st fragment, inside of a large production sproc. It
needs to create and populate #Areas which
-- will be used in JOINS later in the sproc and in the inner sprocs it
calls.
create table #areas
(
state char(2) ,
county char(3)
, SMSA_CD varchar(10) )
Execute dbo.AMS_I_GetAreasV2 -- 12/29/2004 JJA: add
parm for tiered-access support of custom areas using
dbo.AMS_I_GetAreasV2
@.SMSA,
@.S1,
@.C1,
@.SourceTable
, @.CustomID = @.CustomID -- 09/20/2004 JJA: Add support for Custom
Area Definitions as a source for populating #Areas table
, @.UserName = @.UserName -- 12/29/2004 JJA: Make Custom Area
Definitions conform to tiered access rules and limits
-- here is the 2nd fragment (EXECUTEd from above):
ALTER Procedure dbo.AMS_I_GetAreasV2
(
@.SMSA VarChar(10) = NULL,
@.S1 Char(2) = NULL,
@.C1 Char(3) = NULL,
@.SourceTable varchar(1) = 'P' -- P: Purchase-Money R: Refi B:
Both F: FHA V: VA G: All_Govt
, @.CustomID INT = 0 -- 09/20/2004 JJA; 12/09/2004 JJA
, @.Debug int = 0 -- 03/01/2004 JJA
)
As
Set NOCount ON
declare @.err int, @.rows int -- 03/01/2004 JJA - capture essentials for
debugging
declare @.sepid varchar(80)
declare @.time varchar(30)
select @.sepid = ' - AMS_I_GetAreasV2: '
DECLARE @.SMSAV VARCHAR(10)
SELECT @.SMSAV = RTRIM(@.SMSA)
If @.SMSAV IS NULL
begin
SELECT @.SMSAV = ''; -- this will enable PRINT below to occur and
DATALENGTH(@.SMSAV) to be 0 so CASE logic below works
end
select @.time = convert(varchar(30), getdate(), 109)
print @.time + @.sepid + ' entered. SMSA = ' + @.SMSAV + '; SourceTable =' + @.SourceTable + '; CustomID = ' + Convert(Varchar(9),@.CustomID)
if @.CustomID > 0 -- In this mode, a custom area definition is
translated -- 09/20/2004 JJA
BEGIN -- 09/20/2004 JJA
print @.time + @.sepid + ' Custom-Area Definition Mode is in
effect.' -- 09/20/2004 JJA
INSERT INTO #Areas -- 09/20/2004 JJA
EXECUTE @.ERR = dbo.AMS_I_GetAreasV2_CustomAreaTranslator @.CustomID --
09/20/2004 JJA
,@.Debug -- 09/20/2004 JJA
-- , @.SourceTable, @.UserName
-- I had to abandon these new arguments when nesting complaint
showed up
SELECT @.ROWS = @.@.ROWCOUNT -- 09/20/2004 JJA
GOTO CommonExitPoint -- 09/20/2004 JJA
END
--SMSA:
IF datalength(@.SMSAV) = 4 --SMSA
BEGIN
print @.time + @.sepid + ' SMSA Mode in effect.'
If @.SourceTable = 'P'
Begin
INSERT INTO #Areas
SELECT C.State_cd, C.County_Cd, @.SMSAV AS SMSA_CD
FROM County C INNER JOIN SMSA M ON C.SMSA_CD = M.SMSA_CD
WHERE C.SMSA_CD = @.SMSAV AND C.PDATA = 'YES'
.........etc. etc.
-----
ALTER procedure dbo.AMS_I_GetAreasV2_CustomAreaTranslator
----*
-- PURPOSE: Translate an ID for a custom area into a record set of
-- areas that the custom area defines. If any metro-area is part
-- of a custom-area definition, its component STATE and COUNTY are
-- included in this record set (otherwise SMSA is left as NULL).
-- USAGE: Called by AMS_I_GetAreasV2 to populate #Areas
-- HISTORY: 09/23/2004 JJA - implement new sproc
----*
-- EXECUTE dbo.AMS_I_GetAreasV2_CustomAreaTranslator 1,@.Debug=1
(
@.CustomID int -- key to parent table (i.e. has name of this
definition, etc.)
,@.Debug int = 0 -- set default to 1 for Query-Analyzer debugging
-- ,@.SourceTable char(1)
-- ,@.UserName varchar(30)
)
as
DECLARE @.err int
DECLARE @.rows int
DECLARE @.pid varchar(100)
SELECT @.pid = 'AMS_I_GetAreasV2_CustomAreaTranslator: '
SET NOCOUNT ON
if @.Debug = 1 PRINT @.pid + ' entered for CustomID = ' +
CONVERT(VARCHAR(9),@.CustomID)
-- Here, I tried to do:
Create Table #AllowedCounties
(
County_CD CHAR(3),
TypeCounty VARCHAR(60),
State_CD CHAR(2)
)
INSERT INTO #AllowedCounties
EXECUTE dbo.AccountFetchCounties (NULL, @.CategoryCode = @.SourceTable,
@.UserName = @.UserName)
-- SourceTable and Username would have been passed in from callers.
-- Upon successful creation of temporary table #AllowedCounties, it
would have been added to the
-- SELECT just below as another table to JOIN.
-- Yet the INSERT INTO / EXECUTE construct here is disallowed because
at the top #AREAS is being
-- populated and I got the complaint about nesting immediately
trying to compile this "inner" sproc.
SELECT DISTINCT
C.State_CD
, C.County_CD
, SMSA_CD =CASE
When Datalength(X.SMSACBSA) = 10 AND X.SMSACBSA = C.CBSACode +
C.CBSADivision Then C.CBSACode + C.CBSADivision
When Datalength(X.SMSACBSA) = 5 AND X.SMSACBSA = C.CBSACode
Then C.CBSACode
When Datalength(X.SMSACBSA) = 4 AND X.SMSACBSA = C.SMSA_CD
Then C.SMSA_CD
END
FROM dbo.AcctCustomArea X
, dbo.GovtCountiesList C
WHERE
X.CustomID = @.CustomID
AND
CASE
When Datalength(X.SMSACBSA) = 10 AND X.SMSACBSA = C.CBSACode +
C.CBSADivision Then 1
When Datalength(X.SMSACBSA) = 5 AND X.SMSACBSA = C.CBSACode
Then 1
When Datalength(X.SMSACBSA) = 4 AND X.SMSACBSA = C.SMSA_CD
Then 1
When X.SMSACBSA IS NULL AND X.State = C.State_CD
AND X.County = C.County_CD Then 1
ELSE 0 -- where 0 = 1 rejects record
END = 1 -- where 1 = 1 allows record
ORDER BY
C.State_CD
, C.County_CD|||I am sorry I did not chop off all comments from the code posted above
(it is pretty hard to read). I will try to summarize:
In this problem, there are 2 pieces of business logic implemented by
stored procedures and called in numerous places by other stored
procedures.
AMS_I_GetAreasV2 is called to populate a temporary table #AREAS which
is used in JOINS here and is used in reporting elsewhere.
AccountFetchCounties is called to return a set of allowed counties
based on a code and username.
In short, I need to expand the functionality of AMS_I_GetAreasV2 such
that in some cases it calls AccountFetchCounties, joining the allowed
set of rows produced by that sproc with another SELECT.
As I said, when I ran into the complaint about nesting, I tried making
a UDF to EXECUTE AccountFetchCounties but that is disallowed. Then I
tried OPENROWSET with EXECUTE of AccountFetchCounties but that does not
allow parameters to be passed to the sproc. Then I posted the original
question.
To solve this in a semi-ugly way, I have replicated all the
functionality of my sproc, AccountFetchCounties, into a UDF. Then in
the SELECT inside 'AMS_I_GetAreasV2_CustomAreaTranslator', I have
added this UDF which returns a table to my JOIN which works pretty
well.
But I am uncomfortable with the idea of cloning this "business logic"
from SPROC to UDF because of keeping my sanity in the future
maintenance of this code. Thanks in advance for trying to follow my
story and help.|||Here is a better post of code (now cleaned up and fewer comments) that
caused the original nesting error:
-- this CREATE is inside a large production sproc
-- here is the first relevant fragment:
create table #areas
(
state char(2)
, county char(3)
, SMSA_CD varchar(10)
)
Execute dbo.AMS_I_GetAreasV2
@.SMSA,
@.S1,
@.C1,
@.SourceTable
, @.CustomID = @.CustomID
, @.UserName = @.UserName
-- here is the 2nd fragment (EXECUTEd from above):
ALTER Procedure dbo.AMS_I_GetAreasV2
(
@.SMSA VarChar(10) = NULL,
@.S1 Char(2) = NULL,
@.C1 Char(3) = NULL,
@.SourceTable varchar(1) = 'P'
, @.CustomID INT = 0
, @.Debug int = 0
)
As
Set NOCount ON
declare @.err int, @.rows int
DECLARE @.SMSAV VARCHAR(10)
SELECT @.SMSAV = RTRIM(@.SMSA)
If @.SMSAV IS NULL
begin
SELECT @.SMSAV = '';
end
if @.CustomID > 0
BEGIN
INSERT INTO #Areas
EXECUTE @.ERR = dbo.AMS_I_GetAreasV2_CustomAreaTranslator
@.CustomID
,@.Debug
-- , @.SourceTable
-- , @.UserName
-- I had to abandon these new arguments when nesting complaint
-- showed up
SELECT @.ROWS = @.@.ROWCOUNT
GOTO CommonExitPoint
END
--SMSA:
IF datalength(@.SMSAV) = 4
BEGIN
If @.SourceTable = 'P'
Begin
INSERT INTO #Areas
SELECT C.State_cd, C.County_Cd, @.SMSAV AS SMSA_CD
FROM County C INNER JOIN SMSA M ON C.SMSA_CD = M.SMSA_CD
WHERE C.SMSA_CD = @.SMSAV AND C.PDATA = 'YES'
.........etc. etc.
-- here is the 3rd fragment EXECUTED from just above
ALTER procedure dbo.AMS_I_GetAreasV2_CustomAreaTranslator
(
@.CustomID int
,@.Debug int = 0
-- ,@.SourceTable char(1)
-- ,@.UserName varchar(30)
)
as
DECLARE @.err int
DECLARE @.rows int
SET NOCOUNT ON
-- Here, I tried to do:
Create Table #AllowedCounties
(
County_CD CHAR(3),
TypeCounty VARCHAR(60),
State_CD CHAR(2)
)
INSERT INTO #AllowedCounties
EXECUTE dbo.AccountFetchCounties
NULL
, @.CategoryCode = @.SourceTable
, @.UserName = @.UserName
-- SourceTable and Username would have been passed in from callers.
-- Upon successful creation of temporary table #AllowedCounties, it
-- would have been added to the SELECT just below as another table to
JOIN.
-- Yet the INSERT INTO / EXECUTE construct here is disallowed because
-- at the top #AREAS is being populated and I got the complaint about
-- nesting immediately trying to compile this "inner" sproc.
SELECT DISTINCT
C.State_CD
, C.County_CD
, SMSA_CD =CASE
When Datalength(X.SMSACBSA) = 10 AND X.SMSACBSA = C.CBSACode +
C.CBSADivision Then C.CBSACode + C.CBSADivision
When Datalength(X.SMSACBSA) = 5 AND X.SMSACBSA = C.CBSACode
Then C.CBSACode
When Datalength(X.SMSACBSA) = 4 AND X.SMSACBSA = C.SMSA_CD
Then C.SMSA_CD
END
FROM dbo.AcctCustomArea X
, dbo.GovtCountiesList C
WHERE
X.CustomID = @.CustomID
AND
CASE
When Datalength(X.SMSACBSA) = 10 AND X.SMSACBSA = C.CBSACode +
C.CBSADivision Then 1
When Datalength(X.SMSACBSA) = 5 AND X.SMSACBSA = C.CBSACode
Then 1
When Datalength(X.SMSACBSA) = 4 AND X.SMSACBSA = C.SMSA_CD
Then 1
When X.SMSACBSA IS NULL AND X.State = C.State_CD
AND X.County = C.County_CD Then 1
ELSE 0 -- where 0 = 1 rejects record
END = 1 -- where 1 = 1 allows record
ORDER BY
C.State_CD
, C.County_CD|||Please reply if you can get a chance. I tried to describe my problem
better - maybe I gave too much detail. Bottom line is that I had to
clone business logic of a stored procedure into a user defined
function. I do not like having to do this but it works. Like I said, in
trying to extend the processing of the stored procedure, I ran into
multiple restrictions which I have tried to describe.