Showing posts with label local. Show all posts
Showing posts with label local. Show all posts

Tuesday, March 27, 2012

Cursor loop

Hello,

I've created a stored procedure that loops through a cursor, with the
following example code:

DECLARE curPeriod CURSOR LOCAL for SELECT * FROM tblPeriods
DECLARE @.intYear smallint
DECLARE @.intPeriod smallint
DECLARE @.strTekst varchar(50)

OPEN curPeriod

WHILE @.@.FETCH_STATUS=0

BEGIN

FETCH NEXT FROM curPeriod INTO @.intYear, @.intPeriod

SET @.strTekst = CONVERT(varchar, @.intPeriod)

PRINT @.strTekst

END

CLOSE curPeriod
DEALLOCATE curPeriod

The problem is that this loop only executes one time, when I call the
stored procedure a second or third time, nothing happens. It seems that
the Cursor stays at the last record or that @.@.Fetch_status isn't 0. But
I Deallocate the cursor. I have to restart the SQL Server before the
stored procedure can be used again.

Does anyone know why the loop can execute only 1 time?

Greetings,
Chris

*** Sent via Developersdex http://www.developersdex.com ***Chris Zopers wrote:

Quote:

Originally Posted by

Hello,
>
I've created a stored procedure that loops through a cursor, with the
following example code:
>
DECLARE curPeriod CURSOR LOCAL for SELECT * FROM tblPeriods
DECLARE @.intYear smallint
DECLARE @.intPeriod smallint
DECLARE @.strTekst varchar(50)
>
OPEN curPeriod
>
WHILE @.@.FETCH_STATUS=0
>
BEGIN
>
FETCH NEXT FROM curPeriod INTO @.intYear, @.intPeriod
>
SET @.strTekst = CONVERT(varchar, @.intPeriod)
>
PRINT @.strTekst
>
END
>
CLOSE curPeriod
DEALLOCATE curPeriod
>
The problem is that this loop only executes one time, when I call the
stored procedure a second or third time, nothing happens. It seems that
the Cursor stays at the last record or that @.@.Fetch_status isn't 0. But
I Deallocate the cursor. I have to restart the SQL Server before the
stored procedure can be used again.
>
Does anyone know why the loop can execute only 1 time?
>
Greetings,
Chris


Hi Chris,

When you say you have to restart SQL Server before it can be used
again, do you mean the server or just Query Analyser?

I suspect the issue you're having is when you next enter the stored
procedure, the FETCH_STATUS is still as it was at the end of the last
time through the loop - non-zero, and so the loop isn't executed.

I've never seen a good pattern for doing cursors that doesn't look
messy (Since most practicioners tend to try to avoid them in the first
place, no-one spends much time tidying them up).

Normal pattern for me is:

declare cursor x for select ...
declare <variables to hold the columns>

open x

fetch next from x into <list of variables>
while @.@.FETCH_STATUS = 0
begin
--Do stuff

fetch next from x into <list of variables>
end

close x
deallocate x

in short, I've never found a way to do it which doesn't have to have
the same fetch statement in two places.

Damien

PS - Usual recommendation would be to have a list of columns, rather
than select * from... However, there is disagreement over this
particular recommendation, I'd suggest you search the archives for some
lively debate on the matter.|||Chris Zopers (test123test12@.12move.nl) writes:

Quote:

Originally Posted by

I've created a stored procedure that loops through a cursor, with the
following example code:
>
DECLARE curPeriod CURSOR LOCAL for SELECT * FROM tblPeriods
DECLARE @.intYear smallint
DECLARE @.intPeriod smallint
DECLARE @.strTekst varchar(50)
>
OPEN curPeriod
>
WHILE @.@.FETCH_STATUS=0
BEGIN
FETCH NEXT FROM curPeriod INTO @.intYear, @.intPeriod
SET @.strTekst = CONVERT(varchar, @.intPeriod)
PRINT @.strTekst
END
>
CLOSE curPeriod
DEALLOCATE curPeriod
>
The problem is that this loop only executes one time, when I call the
stored procedure a second or third time, nothing happens.


This is because you check @.@.fetch_status before you fetch. This is how
you should write cursor loop:

DECLARE cur INSENSITIVE CURSOR FOR
SELECT col1, col2 FROM tbl

OPEN cur

WHILE 1 = 1
BEGIN
FETCH cur INTO @.par1, @.par2
IF @.@.fetch_status <0
BREAK

-- Do stuff
END

DEALLOCATE cur

Beyond the structure of the cursor loop, please notice:

1) Never use SELECT * with cursor declarations. Add a column to the
table, and your code breaks. That's bad.

2) The cursor must be declared as INSENSITIVE or STATIC (the latter
can be combined with LOCAL, the first cannot). With no specification
you get a dynamic cursor, which is rarely what you want. But dynamic
cursors can have bad impact on both performance and funcion.

--
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se
Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/pr...oads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodin...ions/books.mspx

Cursor is the only choice?

If I want to do a process in a sequence order, is Cursor my only choice?
for example,
----
declare @.ID uniqueidentifier
declare MyCursor cursor local for
select id
from table
where created>thedate
order by created
for read only
open MyCursor
while (1=1)
begin
fetch next from MyCursor into @.ID
if @.@.fetch_status<>0
break
exec DoSomething @.ID
end
close MyCursor
deallocate MyCursor
----
In fact, I have found a way which does NOT work as followed,
select @.Null=dbo.DoSomething(id)
from table
where created>thedate
order by created
As I just metioned, it does not work. There are too many restrictions in the
function declaration. No newid(), no xxxxxx, no xxxxxx, too many
restrictions! But the code is short and clear. I like.
So I would like to know are there another choices for me in this simple
example?Hi, Frank
You can do something this:
declare @.ID int
set @.ID=(
select top 1 id from table
where created>thedate
order by created, id
)
while @.ID is not null begin
exec DoSomething(@.ID)
set @.ID=(
select top 1 id from table
where created>thedate
and id>@.ID
order by created, id
)
end
But this method would not have a better performance than a cursor. The
real solution is to rewrite the DoSomething procedure to process all
rows at once. That's what SQL is for: set-based operations. Please tell
us what DoSomething is supposed to do, or post the actual procedure,
along with DDL (CREATE TABLE-s) and sample data (INSERT INTO ... VALUES
...), so we can really help.
Razvan|||Frank Lee wrote:

> If I want to do a process in a sequence order, is Cursor my only choice?
That depends what the process is. What is the thing represented by
"DoSomething" in your example code? If it is just more data
manipulation then there's a good chance that it can be done without
using a cursor.
David Portas
SQL Server MVP
--|||Go to http://www.sciencecartoonsplus.com/gallery.htm. That is what
your "exec DoSomething @.ID" is like!
I doubt you really need a cursor. In my career (`20 years of SQL
coding, 35 years total) I have written five cursors in production SQL
code; I know that if I had the CASE expression back in the old days, I
know I could have avoided three of them.
We will need more details and probably have to re-write your DDL (good
SQL programmers do not use uniqueidentifier, and names like "id" or
"@.null" even in pseudo-code).|||The Scenario for me is an (I Called) asynchornous Request-and-Process model.
--DDL
Create table Request (
ID uniqueidentifier primary key default newid(),
types int not null, --RequestType, depend on use case, not
important here.
data varchar(255) not null, --pseudo code, maybe many columns,
depend.
created datetime not null default getdate(),
done bit not null default 0
)
go
create trigger xxxxxxxxxxx on Request for insert as
begin
--Do nothing or DoSomethings which will complete in short time
--And then activate a job which process the Request
exec sp_start job xxxxxxxxxxxxxxxxxxxx
end
go
Client-Side (C/S or asp.net) insert something by using
insert into Request (types, data)
The job named xxxxxxxxxxxxxxxxxxxx will auto activate by system every hour
or activate by Request_Insert_Trigger. There is nothing to do for the job
but just exec MyProcessSP. In MyProcessSP, there is a loop to call
DoMyProcessSP @.ID as descripted in last post.
create procedure DoMyProcessSP (@.ID uniqueidentifier) as
begin
declare @.types int
declare @.data varchar(255)
--pseudo code
select @.types=types, @.data=data
from Request
where id=@.id
if @.types=0
begin
insert into Another_A table (xxxxxxxxxxxxxxxxxxxx)
values (data)
exec DoAnotherProcessA @.ID --Depend on business rule. Maybe very
complex and take a long time.
end
else if @.type=1
begin
insert into Another_B table (xxxxxxxxxxxxxxxxxxxx)
values (data)
exec DoAnotherProcessB @.ID --Depend on business rule. Maybe very
complex and take a long time.
end
else
begin
insert into Another_B table (xxxxxxxxxxxxxxxxxxxx)
values (data)
exec DoAnotherProcessC @.ID --Depend on business rule. Maybe very
complex and take a long time.
end
update request
set Done=1
where id=@.id
end
go
create procedure MyProcessSP as --A caller in sequent order
begin
--pseudo code
declare @.ID uniqueidentifier
declare MyCursor cursor local for
select id
from request
where created>thedate
order by created
for read only
open MyCursor
while (1=1)
begin
fetch next from MyCursor into @.ID
if @.@.fetch_status<>0
break
exec DoMyProcessSP @.ID
end
close MyCursor
deallocate MyCursor
end
go
"Razvan Socol" <rsocol@.gmail.com>
'?:1136013807.311645.156520@.g49g2000cwa.googlegroups.com...
> Hi, Frank
> You can do something this:
> declare @.ID int
> set @.ID=(
> select top 1 id from table
> where created>thedate
> order by created, id
> )
> while @.ID is not null begin
> exec DoSomething(@.ID)
> set @.ID=(
> select top 1 id from table
> where created>thedate
> and id>@.ID
> order by created, id
> )
> end
> But this method would not have a better performance than a cursor. The
> real solution is to rewrite the DoSomething procedure to process all
> rows at once. That's what SQL is for: set-based operations. Please tell
> us what DoSomething is supposed to do, or post the actual procedure,
> along with DDL (CREATE TABLE-s) and sample data (INSERT INTO ... VALUES
> ...), so we can really help.
> Razvan
>|||There is a more detail example code in the post I reply to Razvan.
If you do have a good suggestion, please read that post. thx.
"David Portas" <REMOVE_BEFORE_REPLYING_dportas@.acm.org>
'?:1136020809.428204.141060@.o13g2000cwo.googlegroups.com...
> Frank Lee wrote:
>
> That depends what the process is. What is the thing represented by
> "DoSomething" in your example code? If it is just more data
> manipulation then there's a good chance that it can be done without
> using a cursor.
> --
> David Portas
> SQL Server MVP
> --
>|||Frank Lee (Reply@.to.newsgroup) writes:
> The job named xxxxxxxxxxxxxxxxxxxx will auto activate by system every hour
> or activate by Request_Insert_Trigger. There is nothing to do for the job
> but just exec MyProcessSP. In MyProcessSP, there is a loop to call
> DoMyProcessSP @.ID as descripted in last post.
>...
> insert into Another_A table (xxxxxxxxxxxxxxxxxxxx)
> values (data)
> exec DoAnotherProcessA @.ID --Depend on business rule. Maybe very
> complex and take a long time.
>...
So we still can't tell whether you can rewrite this into set-based code.
However, it cannot be denied that there is a trade-off. Even in T-SQL
it is easier to express logic scalarly, handling one row at a time. For
starters, if you want to split code between stored procedures, it's
easy to pass parameters, but you can only pass scalar parameters, not
tables. (Procedures can still share data over tables, see my article
http://www.sommarskog.se/share_data.html for some techniques.)
Rewriting existing code that uses iterative processesing into set-based
can for complex cases be quite an effort. I rewrote a central procedure
of our system in October/November, and it spent over 80 hours on that,
including testing. We have more that we need to rewrite, and the total
estimate is over 500 hours.
Obviously, there is a trade-off. As long as performance is acceptable
for the task, it can be difficult to justify a rewrite, but be prepared
that in some point in the life-time of the system, the situation may
become untenable.
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se
Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/pr...oads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodin...ions/books.mspx|||Frank Lee wrote:
> The Scenario for me is an (I Called) asynchornous Request-and-Process mode
l.
> --DDL
> Create table Request (
> ID uniqueidentifier primary key default newid(),
> types int not null, --RequestType, depend on use case, not
> important here.
> data varchar(255) not null, --pseudo code, maybe many columns,
> depend.
> created datetime not null default getdate(),
> done bit not null default 0
> )
> go
> create trigger xxxxxxxxxxx on Request for insert as
> begin
> --Do nothing or DoSomethings which will complete in short time
> --And then activate a job which process the Request
> exec sp_start job xxxxxxxxxxxxxxxxxxxx
> end
> go
> Client-Side (C/S or asp.net) insert something by using
> insert into Request (types, data)
> The job named xxxxxxxxxxxxxxxxxxxx will auto activate by system every hour
> or activate by Request_Insert_Trigger. There is nothing to do for the job
> but just exec MyProcessSP. In MyProcessSP, there is a loop to call
> DoMyProcessSP @.ID as descripted in last post.
> create procedure DoMyProcessSP (@.ID uniqueidentifier) as
> begin
> declare @.types int
> declare @.data varchar(255)
> --pseudo code
> select @.types=types, @.data=data
> from Request
> where id=@.id
> if @.types=0
> begin
> insert into Another_A table (xxxxxxxxxxxxxxxxxxxx)
> values (data)
> exec DoAnotherProcessA @.ID --Depend on business rule. Maybe very
> complex and take a long time.
> end
> else if @.type=1
> begin
> insert into Another_B table (xxxxxxxxxxxxxxxxxxxx)
> values (data)
> exec DoAnotherProcessB @.ID --Depend on business rule. Maybe very
> complex and take a long time.
> end
> else
> begin
> insert into Another_B table (xxxxxxxxxxxxxxxxxxxx)
> values (data)
> exec DoAnotherProcessC @.ID --Depend on business rule. Maybe very
> complex and take a long time.
> end
> update request
> set Done=1
> where id=@.id
> end
> go
> create procedure MyProcessSP as --A caller in sequent order
> begin
> --pseudo code
> declare @.ID uniqueidentifier
> declare MyCursor cursor local for
> select id
> from request
> where created>thedate
> order by created
> for read only
> open MyCursor
> while (1=1)
> begin
> fetch next from MyCursor into @.ID
> if @.@.fetch_status<>0
> break
> exec DoMyProcessSP @.ID
> end
> close MyCursor
> deallocate MyCursor
> end
> go
> "Razvan Socol" <rsocol@.gmail.com>
> '?:1136013807.311645.156520@.g49g2000cwa.googlegroups.com...
Here's a slightly different approach that has worked for me in the
past. Use your scheduled job or some other scheduled prgram to pull
processes from your request table one at a time. That way you can scale
it by spawning new threads, each of which will take the next pending
request. Also it's probably easier to handle and debug errors if each
job execution is associated with only a single request at a time. You
can use TOP 1 to retrieve the next request. If your processes need to
be serialized then you can use an extra attribute to group those so
that they are taken as a sequence.
I am assuming that these requests are some unrelated and inherently
procedural tasks rather than straight data-manipulation, otherwise
there may be better solutions without cursors or procedural code.
In SQL Server 2005 we have the Service Broker architecture to take care
of messaging and queueing functionality. Take a look at Service Broker
if you haven't already.
David Portas
SQL Server MVP
--|||"David Portas" <REMOVE_BEFORE_REPLYING_dportas@.acm.org>
'?:1136119382.878745.243360@.f14g2000cwb.googlegroups.com...
> Here's a slightly different approach that has worked for me in the
> past. Use your scheduled job or some other scheduled prgram to pull
> processes from your request table one at a time.
Thanks, I use SQL Agent Job.

> That way you can scale
> it by spawning new threads, each of which will take the next pending
> request. Also it's probably easier to handle and debug errors if each
> job execution is associated with only a single request at a time.
Yes, I agree.

> You
> can use TOP 1 to retrieve the next request. If your processes need to
> be serialized then you can use an extra attribute to group those so
> that they are taken as a sequence.
>
Good point. Thx.

> I am assuming that these requests are some unrelated and inherently
> procedural tasks rather than straight data-manipulation, otherwise
> there may be better solutions without cursors or procedural code.
>
Yes, they are unrelated.

>
> In SQL Server 2005 we have the Service Broker architecture to take care
> of messaging and queueing functionality. Take a look at Service Broker
> if you haven't already.
>
Yes, I know. I have test it, and try to rewrite one implementation which
used to use SQL Agent job to implement. However, I find Service Broker is
too BIG for me. I would like, and am planning, to use it to do another big
things. Thanks anyway.

> --
> David Portas
> SQL Server MVP
> --
>sql

Sunday, March 11, 2012

Currency Conversions

Hi!

I am having trouble wrapping my brain around currency conversions.

Here is my situation:

My fact table contains values in local currency with a reference to the currency dimension.

These local currencies need to be converted to two reporting currencies: Actual Rates and Budget Rates.

I have rates on a daily basis for both reporting currencies.

How should my table structure look, and how do i set it up in AS so this works? Ive been fiddeling with this for AGES, getting M:1 conversions to work but not this.

Any help appreciated.

Maybe this thread on currency conversions can help you?

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=151917&SiteID=1

>>

11-29-2005, 8:29 PM UTC

Michael Barrett Jensen

Posts 41

Measure expressions and currency conversion
Was this post helpful ?


OK - here is my scenario... I have a fact table containing one measure: Sales. The values of the measure are stored in the same currency (DKK) for all records. In another fact table I have exchange rates for four different currencies per day for a 15 year period (approx. 22000 records). I have built a cube around these fact tables containing two measure groups.

Measure Group 1
Measure: Sales
Dimensions: Time, Product, Company

Measure Group 2
Measure: Exchange rate
Dimensions: Time, Currency

The only shared dimension between the two measure group is thus Time... The currency dimension contains one attribute hierarchy (CurrencyCode) with IsAggregatable set to False and DefaultMember set to DKK.

For the measure Sales, I have created a measure expression like this:

[Measures].[Sales] / [Measures].[Currency]

I thought this should work - i.e. give me the opportunity to select any of the four available currencies and have the value of Sales displayed accordingly. However - it does not. Instead my Sales measures is multiplied by 4, which corresponds to the number of currencies for which I have exchange rates in my exchange rate fact table. Why is this? Am I not modelling the scenario correctly?

I hope someone can help, since this really puzzles me!


Michael

11-30-2005, 12:06 PM UTC

Chris Webb

Posts 31

Answer Re: Measure expressions and currency conversion
Was this post helpful ?


Hi Michael,

I think I might know what's going on here: you need to give your Currency dimension a many-to-many relationship with Measure Group 1 using Measure Group 2 as the intermediate measure group. Does this work?

Regards,

Chris


Blog at http://spaces.msn.com/members/cwebbbi/

>>

Friday, February 24, 2012

Cube DDL reverse engineer ?

Hi guys

I have built several cubes. However I would need to create local cubes from the built cubes in Analysis Services. As a result I need to work out the DDL for my existing cubes. However the cube contains many mdx calculated members. I was wondering if it would be easier to simply generate the DDL from my existing cube in Analysis Services.

Does anyone know any third party tools that I can use to reverse engineer the DDL from the built cubes in Analysis Services ?

Thanks

Tom

Why not just load it in Server Manager and tell it to Script Database as Create. That should give you the full DDL I believe.|||I want to script the cube not the sql server database.

If there is a way could you please give a more detailed description of the process.

I really appreciate it ! thankyou !

Tom|||The cube is contained in an Analysis Services database, not a SQL Server database. Or are you saying that your AS database contains multiple cubes and you only want to script out one?

Start SQL Server Management Studio
When asked to connect to server drop the Server type down and pick Analysis Services
Expand the databases node.
Right click on a database
Select Script Database as Create To

Alternatively if you want just one cube expadn the cubes node
Right click on the cube you are interested in
Select Script Cube as Create To|||Start SQL Server Management Studio
When asked to connect to server drop the Server type down and pick Analysis Services
Expand the databases node.
Right click on a database
Select Script Database as Create To
__

I've started sql server enterprise manager. When I tried to make a new registration under a sql server group it DOES NOT pick up analysis services. I know they're running on different ports why would sql server manager pickup analysis services ?

can you confirm the process please. I really can't see it working. As there's no possible way for sql server manager to connect to analysis services.

Thankyou
Tom

|||Tom,

I think I see the problem. I'm betting you are using Analysis Services 2000, not Analysis Services 2005...

With SQL Server 2005, the new management tool (called SQL Server Management Studio) replaces Enteprise Manager in SQL Server 2000. SQL Server Management Studio does indeed have the ability to connect to Analysis Services as well as SQL Server. And it has the ability to script the DDL for an entire Analysis Services 2005 database as well as any portion thereof.

However, since you are likely using Analysis Services 2000, this won't work for you. If you need to generate the DDL to create a cube, you'll have to look to some third-party tool options for this as Analysis Manager does not have the ability to generate DDL. Take a look at the short list of options mentioned on Mosha's website at http://www.mosha.com/msolap/util.htm#Metadata. This should at least give you some ideas and options...

Dave Fackler
|||thanks for that at least now I have a good idea what the other person's talking about

Thanks
Tom

Cube back up

dear all
i have a list of 7 cubes on the production server and i intend to bring the back up of 1 cube to my local system(w/o data,just the structure).I took the xmla file by scripting that respective cube and brought that xmla file to my local system. tell me wat i need to do to restore this xmla file to get the structure of my cube

Cheers
sid

If you just need the structure I would suggest scripting the whole database and then running the script on your local server and deleting any cubes that you don't need. This is because you need to have a database to script the cube into and you need to bring the dsv, data sources and database dimensions along so that the cube will work.

I've been playing with a Powershell script to generate the xmla script for a single cube and all the dependant objects, but it's not quite finished. For the time being I would say to go with scripting the whole database and deleting what you don't need later.