Showing posts with label statement. Show all posts
Showing posts with label statement. Show all posts

Monday, March 26, 2012

is it possible to have variant condition clause in procedure?

i want to use OLEDB to build a COM for my app

in the case, i want to execute a select statement which the where-clause is variant.

ex,

select * from db1 where code='abc'

select * from db1 where name='mike'

As it's very difficult to change sql-command in oledb, i want to build a procedure like this,

create procedure viewDB
@.filter CHAR(20)

as

select * from db1 where @.filter

go

but failed!

i tried EXEC(select), but i cant get the variants when building a oledb consumer

No, you cannot pass the whole WHERE clause as a parameter. You could pass only values. In your case if this is predefined set of the types of conditions, then you could create additional parameter in your SP and pass type of the condition there. then, inside of SP, first check type of the query using IF statement and based on it call specific SQL

IF @.MyTYPE='A'

select * from db1 where code=@.filter

ELSE

select * from db1 where name=@.filter

|||

oh, yeah! why i didnt come up with this smart idea, haha

but i found a better solution, bind the columns manually!

|||What is that? Is it constracting SQL statement dinamically inside of SP?|||

no, it's not that!

is easy!

build a SP like this:

create procedure test
@.p char(40)
as
exec( 'select * from testdb where ' + @.p )
go

when executing this sp in sql-server, we can get the columns correctly! but, when using the ole-wizard to build a oledb consumer , the columns disappear. the fact is, the columns lay there steadily, it's ole-wizard didn't bind the columns for us, haha

so let's DIY

|||

But this is worst way to do. It is a pure SQL injection. If I pass next string in your parameter then it will be executed with the different result

Assuming I am passing next value in a parameter

1=1; SHUTDOWN --

Then it will execute your SELECT and then it will shutdown server completely. I could execute DELETE statement or something else. This is how hakers could get control of your server

|||

oh, thanks for telling me that!

but, what if i remove the string after the semi-colon?

my plan is to create a procedure, and use a ATL oledb consumer to access it, if i dont expose the SP name, i think the hackers wont hack me this way

|||They do not need to know your SP name. All the nee to do is to pass value like that to the parameter from your application and job is done. For example, if your screen accepts input for the parameter from outside then screen will accept this value and code will be executed. Another drawback of the dynamic SQL is that it is slower. It means your SP will be recompiled each time when you call it and new execution plan will be prepared.|||

really thanks this piece of infomation!

so, 'select * from table where col=@.p' is safe right?

ok, i will try to re-code my SP

|||

i fond it is almost impossible to code my SP like you suggestted, because my condition clause is so complicate.

i figured out this new plan, and i want to get some advice from you, thx

create procedure proc
@.p1 varchar(10),
@.p2 varchar(10),
...
@.pn varchar(10)

as

if @.p1 is not null
begin
select * into retTable from table where col1= @.p1
--select * into tmpTable from table where col1= @.p1
end
if @.p2 is not null
begin
if object_id('tmpTable) is not null
drop table tmpTable
select * into tmpTable from retTable where col2=@.p1
if object_id('retTable') is not null
drop table retTable
select * into retTable from tmpTable
end

if @.p3 is not null
begin
if object_id('tmpTable') is not null
drop table tmpTable
select * into tmpTable from retTable where col3=@.p3
if object_id('retTable') is not null
drop table retTable
select * into retTable from tmpTable
end

...
...

go

BUT, i wonder if it's efficiency !

could you give me some suggestion or a better solution, thx

|||

I see that code for the second and third IF statements is the same. Does it mean that it suppose to be something like below? It is not an actual code that could work, but shows an idea. If idea is correct then you could pass array of values as one parameter into stored procedure using XML string and then use it inside of the IN clause. If this is what you need, then I will post a code that shows how to pass arrfay of values into SP and how to use it there

if @.p2 is not null
begin
if object_id('tmpTable) is not null
drop table tmpTable
select * into tmpTable from retTable where col2 IN (@.p1, @.p3)
if object_id('retTable') is not null
drop table retTable
select * into retTable from tmpTable
end

|||

well, it should be 'col3' in the 3rd IF statement

so, u mean my idea wont work actually right?

what do u mean pass a parameter using XML string? how can i parse it in the SP?

|||

Here is my article about how touse XML to pass array of values into SP.

http://support.microsoft.com/kb/555266/en-us

I will try to think about ideas how to do this in your case and will let you know

|||

now i have a problem about injection attack!

could you tell me if the following code safe.

procedure sp_a
@.p CHAR(40)
as
select * from tab1 where col1=@.p
go

|||Yes, it is safe if you do not do anything else inside if this SP. Just small suggestion. If you can, select just the fields you need and avoid using *. It will impove performance

Is it possible to fetch the update , insert statement from the log file ?

Is it possible to fetch the historic update , insert statement from the log file ?Not without purchasing some 3rd party software. The only one of which I am aware is a product by Lumigent called (I think) Log Explorer. I have no experience with it, but they have some great customer reviews.

Regards,

Hugh Scott

Originally posted by ligang
Is it possible to fetch the historic update , insert statement from the log file ?

Wednesday, March 21, 2012

Is it possible to create a view within a stored procedure

Is it possible to dynamically create an sql create view statement then execute that sql statement? Or because create views must be the first statement in a query batch, it's not possible?

Hi,

A stored procedure cannot be created with the create View command in it .

But we could create a t-sql string with the create View statement and execute the string with sp_executesql

Though, it returns a Warning message("Cannot add rows to sysdepends for the current stored procedure") the View would be created. The warning message occurs because during the First execution of the SP the View will not be created.

SanDoty

|||

As SanDoty indicated, you cannot create a VIEW inside a STORED PROCEDURE.

However, there are 'tricks', such as using dynamic SQL. Because of various issues, such as dependencies, those 'tricks' should not be considered except under certain circumstances.

However inside a Stored Procedure, you can create a table variable, populate it and use it just like you would use a VIEW.

|||

create proc my_proc as

BEGIN

declare @.sql varchar(max)

select @.sql = 'create view my_sysobjects as select top 5 * from sysobjects'

exec (@.sql)

select * from my_sysobjects

END


go

exec my_proc

|||hi,i tried it and it works..but when i try with my coding to execute, it gives an 'Invalid object name 'vw_test' error.in my stored proc thers some query which does some calculations based on date(im passing in date as parameter in the stored proc - i suspect this might be the cause). how do we overcome this?kindly advice.thanx.

Is it possible to create a view within a stored procedure

Is it possible to dynamically create an sql create view statement then execute that sql statement? Or because create views must be the first statement in a query batch, it's not possible?

Hi,

A stored procedure cannot be created with the create View command in it .

But we could create a t-sql string with the create View statement and execute the string with sp_executesql

Though, it returns a Warning message("Cannot add rows to sysdepends for the current stored procedure") the View would be created. The warning message occurs because during the First execution of the SP the View will not be created.

SanDoty

|||

As SanDoty indicated, you cannot create a VIEW inside a STORED PROCEDURE.

However, there are 'tricks', such as using dynamic SQL. Because of various issues, such as dependencies, those 'tricks' should not be considered except under certain circumstances.

However inside a Stored Procedure, you can create a table variable, populate it and use it just like you would use a VIEW.

|||

create proc my_proc as

BEGIN

declare @.sql varchar(max)

select @.sql = 'create view my_sysobjects as select top 5 * from sysobjects'

exec (@.sql)

select * from my_sysobjects

END


go

exec my_proc

|||hi,i tried it and it works..but when i try with my coding to execute, it gives an 'Invalid object name 'vw_test' error.in my stored proc thers some query which does some calculations based on date(im passing in date as parameter in the stored proc - i suspect this might be the cause). how do we overcome this?kindly advice.thanx.

Monday, March 19, 2012

Is it possible to change the data type during an sql update statement?

Hello,

I have a SQL update statement that updates some user names, however, the user names exceed the length of the data type. Currently, for the column username the data type is set to nvarchar (8).

How can I change that to nvarchar(10) in a SQL Update statement?

Thanks in advance.

You can't put in more data than there is space to store it. If the column holds 8 characters, then you cannot put 10 characters in that same space.

You would need to change the table definition to increase the space allocated for the UserNames.

|||

Thanks for the reply...

I figured that would be the case, but what I need to do is change the data type to 10 before I can update the user names. I also tried using Alter table:

ALTER TABLE table_name
MODIFY column_name column_type;

For some reason, SQL Express did not like the MODIFY function...

Thanks in advance...

|||

Refer to Books Online, Topic: "Alter Table"

Modify is not a T-SQL keyword. You need to use ALTER.

Code Snippet


ALTER TABLE MyTable
ALTER COLUMN MyColumn varchar(10)

You might wish to consider bumping it up a bit more -just in case you later find more is required.

Here is Books Online for SQL Server Express:

SQL Server 2005 Express Books Online Express Edition
http://msdn2.microsoft.com/en-us/library/ms165706.aspx
http://www.microsoft.com/downloads/details.aspx?FamilyId=BE6A2C5D-00DF-4220-B133-29C1E0B6585F

|||

That worked!

I greatly appreciate your response, and for providing me with the SQL links.

Thanks Arnie!

|||It does not work if MyColumn has a relationship with other table. In that case how can I do that? thanks|||

First, remove (or DROP) the PK-FK relationship,

ALTER the column,

then re-establish the relationship.

Is it Possible to a KILL a Process when Process Id is dynamic?

Hi,
I would like to kill a process using the KILL Statement. But the
Process id is dynamic. How can I kill that process?
Example:
Declare @.spid Numeric
SELECT @.spid = spid FROM SPIDTBL
KILL @.spid
Is this possible? How can I do this?
Sevugan.Cuse the process name to determine the spid?
You won't get what you expect,
you get what you deserve, include lessons.
"Sevugan" <Sevugan@.discussions.microsoft.com> wrote in message news:5A855EF7-56B3-4C66-8EF5
-D51DFAEBEC90@.microsoft.com...
> Hi,
> I would like to kill a process using the KILL Statement. But the
> Process id is dynamic. How can I kill that process?
>
> Example:
> Declare @.spid Numeric
> SELECT @.spid = spid FROM SPIDTBL
> KILL @.spid
> Is this possible? How can I do this?
>
> Sevugan.C|||Hi
You have to use Dynamic SQL to do that.
Regards
--
Mike Epprecht, Microsoft SQL Server MVP
Zurich, Switzerland
MVP Program: http://www.microsoft.com/mvp
Blog: http://www.msmvps.com/epprecht/
"Sevugan" wrote:

> Hi,
> I would like to kill a process using the KILL Statement. But the
> Process id is dynamic. How can I kill that process?
>
> Example:
> Declare @.spid Numeric
> SELECT @.spid = spid FROM SPIDTBL
> KILL @.spid
> Is this possible? How can I do this?
>
> Sevugan.C|||Hi,
DECLARE @.lngProcessId NUMERIC
DECLARE @.svSQL VARCHAR(1000)
SET lngProcessId = 51
SET @.svSQL = 'KILL ' + CONVERT(VARCHAR(10), @.lngProcessId)
--PRINT @.svSQL
EXEC @.svSQL
I have used like the above statements block.
I am executing this inside a stored procedure. I am getting an error like th
is
"Could not find stored procedure 'KILL 51'."
How can I resolve this?
Regards,
Sevugan.C
"Mike Epprecht (SQL MVP)" wrote:
> Hi
> You have to use Dynamic SQL to do that.
> Regards
> --
> Mike Epprecht, Microsoft SQL Server MVP
> Zurich, Switzerland
> MVP Program: http://www.microsoft.com/mvp
> Blog: http://www.msmvps.com/epprecht/
>
> "Sevugan" wrote:
>|||EXEC (@.svSQL)
If you EXECute a SQL string you have to enclose it in parenthesis, otherwise
it is treated as a procedure name.
Jacco Schalkwijk
SQL Server MVP
"Sevugan" <Sevugan@.discussions.microsoft.com> wrote in message
news:596AD9F2-78A3-4D50-BF89-13FA3F6E0802@.microsoft.com...
> Hi,
> DECLARE @.lngProcessId NUMERIC
> DECLARE @.svSQL VARCHAR(1000)
> SET lngProcessId = 51
> SET @.svSQL = 'KILL ' + CONVERT(VARCHAR(10), @.lngProcessId)
> --PRINT @.svSQL
> EXEC @.svSQL
> I have used like the above statements block.
> I am executing this inside a stored procedure. I am getting an error like
> this
> "Could not find stored procedure 'KILL 51'."
> How can I resolve this?
>
> Regards,
> Sevugan.C
>
> "Mike Epprecht (SQL MVP)" wrote:
>

Monday, March 12, 2012

Is it possible in single SQL statement

Does anyone know how should I write the sql for getting the following result?

Original Table like below.
----------
[WorkDay] [AgentCode]
06/12/01 3
06/12/02 2
06/12/02 3
06/12/03 2
06/12/03 3
----------

Curernt SQL:

When I put an "agentcode=2" in 'WHERE' clause, the result does not have '06/12/01' row.

Example,
SELECT DISTINCT WorkDay, AgentCode FROM MasterScheduleTransaction WHERE AgentCode=2
----------
[WorkDay] [AgentCode]
06/12/02 2
06/12/03 2
----------

I would like to know the agent is in the specified date.
The expected result like below.
----------
[WorkDay] [AgentCode]
06/12/01 NULL
06/12/02 2
06/12/03 2
----------

Please help its urgentwhy would the result have a row for 06/12/01 when you are telling it to get the rows for agentcode=2... it will discard all the rows having agentcode <> 2.
I think you need to use a self outer join to get the expected result.|||SELECT DISTINCT
Workday,
CASE WHEN AgentCode = 2 THEN
2
ELSE
NULL
END AS AgentCodeIfTwo
FROM OriginalTable|||or when your table is called justanotherday

SELECT DISTINCT
a.workday, b.agentcode
FROM
justanotherday a
LEFT JOIN
justanotherday b
ON
(a.workday = b.workday AND b.agentcode = 2)|||I suppose if you are trying to kill time and want to scan the table twice...|||:D

Well, that shouldn't be too hard... in five years are only 1825 date records... so...|||...assuming only 1 record per day, in which case why select DISTINCT? There is no way to tell how many records are in the table.|||no... i mean.. it's 'only' 1825 records against x records in 5 years... if x is not extremely large, no SQL interpreter should have problems with it in my opinion... or am i totally wrong here?|||The issue isn't that there would be a noticable difference in performance against small record sets. The issue is that the solution you proposed is sub-optimal, and might encourage someone to use the same method against larger databases. We try to propose (and frequently argue about) "best practices" on this forum. If you think that the algorithm you proposed is more efficient than Pootle's method, then take the opportunity to justify your opinion.|||ok... you are right about that... my solution is not really an optimal one :)

Friday, March 9, 2012

is it easy to amend an insert statement.

I am trying to amend an SQL insert statement but it is not working.

It is as follows can anyone tell me what i am doing wrong.

<asp:SqlDataSourceID="SqlDataSource1"runat="server"ConflictDetection="CompareAllValues"

ConnectionString="<%$ ConnectionStrings:ConnectionString2 %>"DeleteCommand="DELETE FROM [useridTest] WHERE [userID] = @.original_userID AND [userName] = @.original_userName AND [listCopy] = @.original_listCopy"

InsertCommand="INSERT INTO [useridTest] ([userID], [userName], [listCopy]) VALUES (<% user.ProviderUserKey.ToString() %>, @.userName, @.listCopy)"

Please add this to your SqlDataSource:OnInserting="SQLDataSource2_OnInserting"

and

<InsertParameters>

<asp:ParameterName="userID"Type="String"/>

</InsertParameters>

Code:

protectedvoid SQLDataSource2_OnInserting(object sender,SqlDataSourceCommandEventArgs e)

{

e.Command.Parameters["@.userID"].Value =user.ProviderUserKey.ToString();

}

Friday, February 24, 2012

Is DB Mirroring supported in SQL 2005?

I just read the follwing statement in the help file.
Important:
Microsoft support policies do not apply to the database mirroring feature in
SQL Server 2005. Database mirroring is currently disabled by default, but may
be enabled for evaluation purposes only by using trace flag 1400 as a startup
parameter. (For more information about trace flags, see Trace Flags
(Transact-SQL).) Database mirroring should not be used in production
environments, and Microsoft support services will not support databases or
applications that use database mirroring. Database mirroring documentation is
included in SQL Server 2005 for evaluation purposes only, and the
Documentation Policy for SQL Server 2005 Support and Upgrade does not apply
to the database mirroring documentation.
I know that mirroring wasn't available in the original release, but was
available after installing sp1, which I have installed. Is it supported and
safe to use?
Another question I have is, If a snapshot is created off the mirror, which
is on a seperate server from production, and mirroring with high protection
is being used, is it possible for a long running report to cause performance
issues on the prod server? Or could the report prevent the mirror from
getting updated?
Thanks
--
MG>I just read the follwing statement in the help file.
When you upgraded your server to SP1, did you also install the updated Books
Online documentation? The help files are updated frequently. The most
recent official release is July 2006:
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
But if you want the most recent copy (including some information on SP2) you
can get it here:
http://www.microsoft.com/downloads/details.aspx?familyid=19db0b42-a5b2-456f-9c5c-f295cdd58d7a
A|||Thanks
I only installed sp1, but not the updated documentation.
--
MG
"Aaron Bertrand [SQL Server MVP]" wrote:
> >I just read the follwing statement in the help file.
> When you upgraded your server to SP1, did you also install the updated Books
> Online documentation? The help files are updated frequently. The most
> recent official release is July 2006:
> http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
> But if you want the most recent copy (including some information on SP2) you
> can get it here:
> http://www.microsoft.com/downloads/details.aspx?familyid=19db0b42-a5b2-456f-9c5c-f295cdd58d7a
> A
>
>

Is DB Mirroring supported in SQL 2005?

I just read the follwing statement in the help file.
Important:
Microsoft support policies do not apply to the database mirroring feature in
SQL Server 2005. Database mirroring is currently disabled by default, but may
be enabled for evaluation purposes only by using trace flag 1400 as a startup
parameter. (For more information about trace flags, see Trace Flags
(Transact-SQL).) Database mirroring should not be used in production
environments, and Microsoft support services will not support databases or
applications that use database mirroring. Database mirroring documentation is
included in SQL Server 2005 for evaluation purposes only, and the
Documentation Policy for SQL Server 2005 Support and Upgrade does not apply
to the database mirroring documentation.
I know that mirroring wasn't available in the original release, but was
available after installing sp1, which I have installed. Is it supported and
safe to use?
Another question I have is, If a snapshot is created off the mirror, which
is on a seperate server from production, and mirroring with high protection
is being used, is it possible for a long running report to cause performance
issues on the prod server? Or could the report prevent the mirror from
getting updated?
Thanks
MG
>I just read the follwing statement in the help file.
When you upgraded your server to SP1, did you also install the updated Books
Online documentation? The help files are updated frequently. The most
recent official release is July 2006:
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
But if you want the most recent copy (including some information on SP2) you
can get it here:
http://www.microsoft.com/downloads/details.aspx?familyid=19db0b42-a5b2-456f-9c5c-f295cdd58d7a
A
|||Thanks
I only installed sp1, but not the updated documentation.
MG
"Aaron Bertrand [SQL Server MVP]" wrote:

> When you upgraded your server to SP1, did you also install the updated Books
> Online documentation? The help files are updated frequently. The most
> recent official release is July 2006:
> http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
> But if you want the most recent copy (including some information on SP2) you
> can get it here:
> http://www.microsoft.com/downloads/details.aspx?familyid=19db0b42-a5b2-456f-9c5c-f295cdd58d7a
> A
>
>

Is DB Mirroring supported in SQL 2005?

I just read the follwing statement in the help file.
Important:
Microsoft support policies do not apply to the database mirroring feature in
SQL Server 2005. Database mirroring is currently disabled by default, but ma
y
be enabled for evaluation purposes only by using trace flag 1400 as a startu
p
parameter. (For more information about trace flags, see Trace Flags
(Transact-SQL).) Database mirroring should not be used in production
environments, and Microsoft support services will not support databases or
applications that use database mirroring. Database mirroring documentation i
s
included in SQL Server 2005 for evaluation purposes only, and the
Documentation Policy for SQL Server 2005 Support and Upgrade does not apply
to the database mirroring documentation.
I know that mirroring wasn't available in the original release, but was
available after installing sp1, which I have installed. Is it supported and
safe to use?
Another question I have is, If a snapshot is created off the mirror, which
is on a seperate server from production, and mirroring with high protection
is being used, is it possible for a long running report to cause performance
issues on the prod server? Or could the report prevent the mirror from
getting updated?
Thanks
--
MG>I just read the follwing statement in the help file.
When you upgraded your server to SP1, did you also install the updated Books
Online documentation? The help files are updated frequently. The most
recent official release is July 2006:
http://www.microsoft.com/technet/pr...oads/books.mspx
But if you want the most recent copy (including some information on SP2) you
can get it here:
http://www.microsoft.com/downloads/.../>
295cdd58d7a
A|||Thanks
I only installed sp1, but not the updated documentation.
--
MG
"Aaron Bertrand [SQL Server MVP]" wrote:

> When you upgraded your server to SP1, did you also install the updated Boo
ks
> Online documentation? The help files are updated frequently. The most
> recent official release is July 2006:
> http://www.microsoft.com/technet/pr...oads/books.mspx
> But if you want the most recent copy (including some information on SP2) y
ou
> can get it here:
> http://www.microsoft.com/downloads/...
-f295cdd58d7a
> A
>
>

Monday, February 20, 2012

Is Cursor Best Way To Go?

I need to get two values from a complex SQL statement which returns a single
record and use those two values to update a single record in a table. In
order to assign those two values to variables and then use those variables
in the UPDATE statement, I created a cursor and used Fetch Next... Into.
This way, I only have to call the complex SQL once instead of twice.
This seems like the best way to go. However, I've always used cursors for
scrolling through resultsets. In this case, though, there is just a single
record being returned, and the cursor doesn't scroll.
Is that the most efficient way to go, or is there a better way to be able to
use both values from the SQL statement without having to call it twice?
Thanks.Hi Neil
I'd need more details regarding the query/DDL to say anything too
meaningful, but certainly a set-based solution is always preferable to
an iterative/cursor-solution.|||here is a guess without seeing your code.
declare @.v1 int, @.v2 int
select @.v1=[col1], @.v2=[colx]
from (
-- your complex query
) as derived_table
-oj
"Neil" <nospam@.nospam.net> wrote in message
news:vhAne.4180$s64.2269@.newsread1.news.pas.earthlink.net...
>I need to get two values from a complex SQL statement which returns a
>single record and use those two values to update a single record in a
>table. In order to assign those two values to variables and then use those
>variables in the UPDATE statement, I created a cursor and used Fetch
>Next... Into. This way, I only have to call the complex SQL once instead
>of twice.
> This seems like the best way to go. However, I've always used cursors for
> scrolling through resultsets. In this case, though, there is just a single
> record being returned, and the cursor doesn't scroll.
> Is that the most efficient way to go, or is there a better way to be able
> to use both values from the SQL statement without having to call it twice?
> Thanks.
>|||SQL Server doesn't support the standard SQL syntax for this but it does
have a proprietary syntax to do the same job:
UPDATE T1
SET x = foo,
y = bar
FROM
(SELECT foo, bar /* your query here */
FROM ... ) AS T2
WHERE T2.key_col = T1.key_col
/* join condition should yield a single row from T2 for each row in
T1 */

> I've always used cursors for
> scrolling through resultsets
Really? For what purpose? Cursors should be the rare exception rather
than the rule. Usually there are better set-based solutions.
David Portas
SQL Server MVP
--|||> SQL Server doesn't support the standard SQL syntax for this but it does
> have a proprietary syntax to do the same job:
> UPDATE T1
> SET x = foo,
> y = bar
> FROM
> (SELECT foo, bar /* your query here */
> FROM ... ) AS T2
> WHERE T2.key_col = T1.key_col
> /* join condition should yield a single row from T2 for each row in
> T1 */
Yes, that was what I was looking for (though I needed to use UPDATE T1
SET... From T1, (Select foo...) As T2...)
Also, since I'm only updating a single row in T1, and since T2 only returns
a single row with values, I eliminated the WHERE T2.keycol=T1.keycol. My SQL
looks like:
UPDATE T1
SET X = T2.FOO, Y=T2.BAR
FROM T1, (SELECT FOO, BAR FROM MYQUERY WHERE ID=@.VALUE) AS T2
WHERE T1.ID=@.VALUE
Do you see any problem with that?

> Really? For what purpose? Cursors should be the rare exception rather
> than the rule. Usually there are better set-based solutions.
I guess one of the main areas where I've used them is in order-rearranging
functions -- such as where there are a set of items in a table, each with a
value in a field that specifies the order. The user clicks, say, an up arrow
in the interface, and the current item needs to move up one in order --
decrement it's field value by one, and increment the preceding item's by
one.
Another time I used a cursor was in a procedure in which the length of two
fields combined needed to be compared to a value and then, based on the
length of the combined fields, different values would be placed in a certain
field. I suppose that could have just been done with a set-based solution;
but the cursor seemed more straightforward. It was also only dealing with
one record at a time.
Thanks for your help!
Neil

> --
> David Portas
> SQL Server MVP
> --
>|||Re-arranging order based on a column (pos):
UPDATE foo
SET pos = CASE pos
WHEN @.old_pos
THEN @.new_pos
ELSE pos + SIGN(@.old_pos - @.new_pos)
END
WHERE pos BETWEEN @.old_pos AND @.new_pos
OR pos BETWEEN @.new_pos AND @.old_pos
Update different columns based on the length of a string value:
UPDATE YourTable
SET col1 =
CASE
WHEN LEN(x+y)<=10
THEN a ELSE b END,
col2 =
CASE
WHEN LEN(x+y)>10
THEN a ELSE b END
WHERE ...
David Portas
SQL Server MVP
--
UPDATE|||David Portas Jun 2, 7:07 am show options
Newsgroups: comp.databases.ms-sqlserver,
microsoft.public.sqlserver.programming
From: "David Portas" <REMOVE_BEFORE_REPLYING_dpor...@.acm.o=ADrg> - Find
messages by this author
Date: 2 Jun 2005 04:07:17 -0700
Local: Thurs,Jun 2 2005 7:07 am
Subject: Re: Is Cursor Best Way To Go?
Reply | Reply to Author | Forward | Print | Individual Message | Show
original | Report Abuse
Re-arranging order based on a column (pos):
UPDATE foo
SET pos =3D CASE pos
WHEN @.old_pos
THEN @.new_pos
ELSE pos + SIGN(@.old_pos - @.new_pos)
END
WHERE pos BETWEEN @.old_pos AND @.new_pos
OR pos BETWEEN @.new_pos AND @.old_pos;
Very neat! I always did a monster CASE expression with extra WHEN
clauses based on (old_pos ' newpos).|||Hi, David.
Here's another one for you. I have an sp that takes various input parameters
for a customer, and processes the data using various case statements. I now
want to run this sp for all customers on a nightly basis. My immediate
reaction, as previously, would be to use a cursor to loop through all the
customers, get the input parameters for the sp from the Customer table, and
call the sp once for each customer. Is there a way to do this without a
cursor?
Thanks,
Neil
"David Portas" <REMOVE_BEFORE_REPLYING_dportas@.acm.org> wrote in message
news:1117710437.665131.255080@.g47g2000cwa.googlegroups.com...
> Re-arranging order based on a column (pos):
> UPDATE foo
> SET pos = CASE pos
> WHEN @.old_pos
> THEN @.new_pos
> ELSE pos + SIGN(@.old_pos - @.new_pos)
> END
> WHERE pos BETWEEN @.old_pos AND @.new_pos
> OR pos BETWEEN @.new_pos AND @.old_pos
> Update different columns based on the length of a string value:
> UPDATE YourTable
> SET col1 =
> CASE
> WHEN LEN(x+y)<=10
> THEN a ELSE b END,
> col2 =
> CASE
> WHEN LEN(x+y)>10
> THEN a ELSE b END
> WHERE ...
> --
> David Portas
> SQL Server MVP
> --
>
>
>
> UPDATE
>|||Neil (nospam@.nospam.net) writes:
> Here's another one for you. I have an sp that takes various input
> parameters for a customer, and processes the data using various case
> statements. I now want to run this sp for all customers on a nightly
> basis. My immediate reaction, as previously, would be to use a cursor to
> loop through all the customers, get the input parameters for the sp from
> the Customer table, and call the sp once for each customer. Is there a
> way to do this without a cursor?
Yes, but you will of course have to rewrite the procedure, so that it
works with many customers. To do this, you need to pass the input
parameters in a table rather than as parameter. This table can be a temp
table, or a permanent table which is keyed by @.@.spid or similar. I discuss
this on http://www.sommarskog.se/share_data.html#temptables.
Well, rather you would write a new procedure that works with many, and
then rewrite the old procedure to be a wrapper on the new procedure.
Now, whether you actually should go this route depends. Let's say that
it takes 10 minutes to run a cursor over all customers and call the
existing procedure, and that you have plenty of time to spare in the
night. In this case, it's not likely to be worth the development effort.
Also, if you opt to use a temp table to pass the input parameters, the
procedure will be recompiled each time. This will have the net effect
that calls for single customers will now be more expensive, and could
even be performance problems, if the procedure is huge.
We actually did this exercise with a core procedure in our system, and
in our case it was really necessary. But it was a major developement task.
Our estimate was 200 hours for development, but I think the true outcome
was more than 300 hours. But that was a long procedure, on 700-800 lines
and which called several sub-procedures. The final multi-version is a
3000-line monster with no less than 43 table variables.
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se
Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techin.../2000/books.asp|||Everything Erland has said. This is where it pays to have a good design
pattern from kick-off. For an UPDATE/INSERT/DELETE proc servicing the
UI you may typically want to pass parameters for a single row. For
procs that implement other business logic however, you should generally
design with a set-based approach in mind. Unfortunately, programmers
used to other languages too often try to encapsulate all logic in procs
that act like scalar functions - a sure route to cursor hell!
David Portas
SQL Server MVP
--

Is Cursor Best Way To Go?

I need to get two values from a complex SQL statement which returns a single
record and use those two values to update a single record in a table. In
order to assign those two values to variables and then use those variables
in the UPDATE statement, I created a cursor and used Fetch Next... Into.
This way, I only have to call the complex SQL once instead of twice.

This seems like the best way to go. However, I've always used cursors for
scrolling through resultsets. In this case, though, there is just a single
record being returned, and the cursor doesn't scroll.

Is that the most efficient way to go, or is there a better way to be able to
use both values from the SQL statement without having to call it twice?

Thanks.Hi Neil

I'd need more details regarding the query/DDL to say anything too
meaningful, but certainly a set-based solution is always preferable to
an iterative/cursor-solution.|||here is a guess without seeing your code.

declare @.v1 int, @.v2 int
select @.v1=[col1], @.v2=[colx]
from (
-- your complex query
) as derived_table

--
-oj

"Neil" <nospam@.nospam.net> wrote in message
news:vhAne.4180$s64.2269@.newsread1.news.pas.earthl ink.net...
>I need to get two values from a complex SQL statement which returns a
>single record and use those two values to update a single record in a
>table. In order to assign those two values to variables and then use those
>variables in the UPDATE statement, I created a cursor and used Fetch
>Next... Into. This way, I only have to call the complex SQL once instead
>of twice.
> This seems like the best way to go. However, I've always used cursors for
> scrolling through resultsets. In this case, though, there is just a single
> record being returned, and the cursor doesn't scroll.
> Is that the most efficient way to go, or is there a better way to be able
> to use both values from the SQL statement without having to call it twice?
> Thanks.|||SQL Server doesn't support the standard SQL syntax for this but it does
have a proprietary syntax to do the same job:

UPDATE T1
SET x = foo,
y = bar
FROM
(SELECT foo, bar /* your query here */
FROM ... ) AS T2
WHERE T2.key_col = T1.key_col
/* join condition should yield a single row from T2 for each row in
T1 */

> I've always used cursors for
> scrolling through resultsets

Really? For what purpose? Cursors should be the rare exception rather
than the rule. Usually there are better set-based solutions.

--
David Portas
SQL Server MVP
--|||> SQL Server doesn't support the standard SQL syntax for this but it does
> have a proprietary syntax to do the same job:
> UPDATE T1
> SET x = foo,
> y = bar
> FROM
> (SELECT foo, bar /* your query here */
> FROM ... ) AS T2
> WHERE T2.key_col = T1.key_col
> /* join condition should yield a single row from T2 for each row in
> T1 */

Yes, that was what I was looking for (though I needed to use UPDATE T1
SET... From T1, (Select foo...) As T2...)

Also, since I'm only updating a single row in T1, and since T2 only returns
a single row with values, I eliminated the WHERE T2.keycol=T1.keycol. My SQL
looks like:

UPDATE T1
SET X = T2.FOO, Y=T2.BAR
FROM T1, (SELECT FOO, BAR FROM MYQUERY WHERE ID=@.VALUE) AS T2
WHERE T1.ID=@.VALUE

Do you see any problem with that?

>> I've always used cursors for
>> scrolling through resultsets
> Really? For what purpose? Cursors should be the rare exception rather
> than the rule. Usually there are better set-based solutions.

I guess one of the main areas where I've used them is in order-rearranging
functions -- such as where there are a set of items in a table, each with a
value in a field that specifies the order. The user clicks, say, an up arrow
in the interface, and the current item needs to move up one in order --
decrement it's field value by one, and increment the preceding item's by
one.

Another time I used a cursor was in a procedure in which the length of two
fields combined needed to be compared to a value and then, based on the
length of the combined fields, different values would be placed in a certain
field. I suppose that could have just been done with a set-based solution;
but the cursor seemed more straightforward. It was also only dealing with
one record at a time.

Thanks for your help!

Neil

> --
> David Portas
> SQL Server MVP
> --|||Re-arranging order based on a column (pos):

UPDATE foo
SET pos = CASE pos
WHEN @.old_pos
THEN @.new_pos
ELSE pos + SIGN(@.old_pos - @.new_pos)
END
WHERE pos BETWEEN @.old_pos AND @.new_pos
OR pos BETWEEN @.new_pos AND @.old_pos

Update different columns based on the length of a string value:

UPDATE YourTable
SET col1 =
CASE
WHEN LEN(x+y)<=10
THEN a ELSE b END,
col2 =
CASE
WHEN LEN(x+y)>10
THEN a ELSE b END
WHERE ...

--
David Portas
SQL Server MVP
--

UPDATE|||David Portas Jun 2, 7:07 am show options

Newsgroups: comp.databases.ms-sqlserver,
microsoft.public.sqlserver.programming
From: "David Portas" <REMOVE_BEFORE_REPLYING_dpor...@.acm.o*rg> - Find
messages by this author
Date: 2 Jun 2005 04:07:17 -0700
Local: Thurs,Jun 2 2005 7:07 am
Subject: Re: Is Cursor Best Way To Go?
Reply | Reply to Author | Forward | Print | Individual Message | Show
original | Report Abuse

Re-arranging order based on a column (pos):

UPDATE foo
SET pos = CASE pos
WHEN @.old_pos
THEN @.new_pos
ELSE pos + SIGN(@.old_pos - @.new_pos)
END
WHERE pos BETWEEN @.old_pos AND @.new_pos
OR pos BETWEEN @.new_pos AND @.old_pos;

Very neat! I always did a monster CASE expression with extra WHEN
clauses based on (old_pos ?? newpos).|||Hi, David.

Here's another one for you. I have an sp that takes various input parameters
for a customer, and processes the data using various case statements. I now
want to run this sp for all customers on a nightly basis. My immediate
reaction, as previously, would be to use a cursor to loop through all the
customers, get the input parameters for the sp from the Customer table, and
call the sp once for each customer. Is there a way to do this without a
cursor?

Thanks,

Neil

"David Portas" <REMOVE_BEFORE_REPLYING_dportas@.acm.org> wrote in message
news:1117710437.665131.255080@.g47g2000cwa.googlegr oups.com...
> Re-arranging order based on a column (pos):
> UPDATE foo
> SET pos = CASE pos
> WHEN @.old_pos
> THEN @.new_pos
> ELSE pos + SIGN(@.old_pos - @.new_pos)
> END
> WHERE pos BETWEEN @.old_pos AND @.new_pos
> OR pos BETWEEN @.new_pos AND @.old_pos
> Update different columns based on the length of a string value:
> UPDATE YourTable
> SET col1 =
> CASE
> WHEN LEN(x+y)<=10
> THEN a ELSE b END,
> col2 =
> CASE
> WHEN LEN(x+y)>10
> THEN a ELSE b END
> WHERE ...
> --
> David Portas
> SQL Server MVP
> --
>
>
>
> UPDATE|||Neil (nospam@.nospam.net) writes:
> Here's another one for you. I have an sp that takes various input
> parameters for a customer, and processes the data using various case
> statements. I now want to run this sp for all customers on a nightly
> basis. My immediate reaction, as previously, would be to use a cursor to
> loop through all the customers, get the input parameters for the sp from
> the Customer table, and call the sp once for each customer. Is there a
> way to do this without a cursor?

Yes, but you will of course have to rewrite the procedure, so that it
works with many customers. To do this, you need to pass the input
parameters in a table rather than as parameter. This table can be a temp
table, or a permanent table which is keyed by @.@.spid or similar. I discuss
this on http://www.sommarskog.se/share_data.html#temptables.

Well, rather you would write a new procedure that works with many, and
then rewrite the old procedure to be a wrapper on the new procedure.

Now, whether you actually should go this route depends. Let's say that
it takes 10 minutes to run a cursor over all customers and call the
existing procedure, and that you have plenty of time to spare in the
night. In this case, it's not likely to be worth the development effort.
Also, if you opt to use a temp table to pass the input parameters, the
procedure will be recompiled each time. This will have the net effect
that calls for single customers will now be more expensive, and could
even be performance problems, if the procedure is huge.

We actually did this exercise with a core procedure in our system, and
in our case it was really necessary. But it was a major developement task.
Our estimate was 200 hours for development, but I think the true outcome
was more than 300 hours. But that was a long procedure, on 700-800 lines
and which called several sub-procedures. The final multi-version is a
3000-line monster with no less than 43 table variables.

--
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techin.../2000/books.asp|||Everything Erland has said. This is where it pays to have a good design
pattern from kick-off. For an UPDATE/INSERT/DELETE proc servicing the
UI you may typically want to pass parameters for a single row. For
procs that implement other business logic however, you should generally
design with a set-based approach in mind. Unfortunately, programmers
used to other languages too often try to encapsulate all logic in procs
that act like scalar functions - a sure route to cursor hell!

--
David Portas
SQL Server MVP
--|||David Portas (REMOVE_BEFORE_REPLYING_dportas@.acm.org) writes:
> Everything Erland has said. This is where it pays to have a good design
> pattern from kick-off. For an UPDATE/INSERT/DELETE proc servicing the
> UI you may typically want to pass parameters for a single row. For
> procs that implement other business logic however, you should generally
> design with a set-based approach in mind. Unfortunately, programmers
> used to other languages too often try to encapsulate all logic in procs
> that act like scalar functions - a sure route to cursor hell!

Permit me to expand a bit on what I touched in my previous post.

In many cases it is reasonable to write a procedure that operates
on a scalar set of values. It cannot be denied that writing such a
procedure is simpler, and thus cuts development costs at that stage.

Passing data in tables is actually quite messy. Let's look at the options:
1) Use a temp table. The caller must create the temp table, and the callee
trust the caller. If the procedure is called from many places, many
callers must create the table. This can be address with an include-
file, if you have the luxury of a preprocessor. We have that, but it's
not a standard feature.
And if even you get by all this, the callee is recompiled for each
new instance of the caller. This can be expensive.
2) A permanent table, typically spid-keyed. We use this technique for the
really heavy-duty stuff. If you make this routine, you get lots of
these tables. Note also that the tables are typically stored disjunct
in the version-control system, which means that procedure and
"parameter list" are in two places.
3) Clients can't use any of 1 or 2, but they can pass comma-separated
lists or XML-documents. But if A_SP calls B_SP, it would be a bad
idea if A_SP built an XML document from its data, only to be able
to call B_SP. What you can to is to have a wrapper that accepts
the XML document, and unpacks that into the temp table or spid-
keyed table. If the client is mainly interested in single-row
operations, it probably needs a scalar wrapper as well. Else, it
will be a lot extra development overhead to build XML documents.

So, clearly, if you at point A in your devleopment cycle only have a need
for a procedure that operates on scalar parameters, you write a procedure
that works with scalar procedure only, because that is what you are paid
for.

If you later at point B need to do the same operation on many rows,
you have to make a judicious choice between:

1) Write a cursor loop.
2) Just forget about the old procedure, and write a new set-based.
3) Replace the old procedure.

If the logic of the procedure is trivial, like "IF NOT EXISTS INSERT ELSE
UPDATE" you should pick #2. But say that the logic is non-trivial, for
instance includes updates to dependent tables in some unnormalised
scenario, then at some point #2 becomes completely impermissible. At
this point #1 can very well be the best pick. Say that you know that
it will be rare that the cursor will comprise as much as 100 rows. If
the procedure takes 100 ms to run, it may be very difficult to motivate
to rewrite the old procedure, if this would take 100 hours.

There is also another issue here that is worth mentioning. Say that your
procedure performs some sort of INSERT operation (in a couple of tables),
and the data comes from some less trustable source, which thus may
supply non-conformant data. If you have a scalar procedure, error
handling is fairly simple. You can do explicit checks on anticipated
errors, but you can be fairly relaxed, because if some data violates a
constraint or trigger check, the operation will fail.

This because a lot more complex if you accept input data in a table.
Because if you apply the same strategy, 1000 rows could fail to insert
when there is an error in a single one. This could very likely be
entirely unacceptable. Thus in case, you will need to duplicate all
constraint and trigger checks in your code, so you can mark which rows
that are illegal.

So while it is easy to say "replace cursor loops with set-based
statments", one should realise that in complex cases, this is far from
trivial.

--
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techin.../2000/books.asp

is case statement the only way

Hi

I need to generate a SQL report like below,its basically calculating the count of students

For

District Level

then for

Region Level

then for

Each School under a Region

Like the Display Below

District summary

Total

Male

Femal

Indian

White

Asian

--

--

--

Type1

22

33

22

11

11

11

23

11

13

Type2

2

…6

…7

;;;;

13

14

Region 1

Region 2...................Region 8

Each School

School1....School 15

Do I have to have

case for each Type for each Race

and then

for Each Levels

of

District

Region

And 500 Schools?

Please Help

Thanks

Could you post your DDL statements and some sample data? This will help us understand your problem and hopefully provide a solution....
|||

From what I understand you may be looking for the PIVOT operator which is available in SQL 2005.

http://technet.microsoft.com/en-us/library/ms177410.aspx

|||

SELECT distinct SCHOOL_REGION,SCHOOL_NUMBER,ETHNICITY,SCH.S_SCHL_NAME,

INTV.Intervention_ ID,

case

INTV.Intervention_ ID when '1' then

(CASE STDM.ETHNICITY when 'A'

then count(STDM.student_id )

END )as Asian,

(CASE STDM.ETHNICITY when 'B'

then count(STDM.student_id )

END )as Black,

(CASE STDM.ETHNICITY when 'H'

then count(STDM.student_id )

END )as Hispanic,

(CASE STDM.ETHNICITY when 'I'

then count(STDM.student_id )

END )as Indian,

(CASE STDM.ETHNICITY when 'M'

then count(STDM.student_id )

END )as Multiracial,

(CASE STDM.ETHNICITY when 'W'

then count(STDM.student_id )

END )as White

case

INTV.Intervention_ ID when '2' then

(CASE STDM.ETHNICITY when 'A'

then count(STDM.student_id )

END )as Asian,

(CASE STDM.ETHNICITY when 'B'

then count(STDM.student_id )

END )as Black,

(CASE STDM.ETHNICITY when 'H'

then count(STDM.student_id )

END )as Hispanic,

(CASE STDM.ETHNICITY when 'I'

then count(STDM.student_id )

END )as Indian,

(CASE STDM.ETHNICITY when 'M'

then count(STDM.student_id )

END )as Multiracial,

(CASE STDM.ETHNICITY when 'W'

then count(STDM.student_id )

END )as White

........

-

-

case

INTV.Intervention_ ID when....... '14' then

(CASE STDM.ETHNICITY when 'A'

then count(STDM.student_id )

END )as Asian,

(CASE STDM.ETHNICITY when 'B'

then count(STDM.student_id )

END )as Black,

(CASE STDM.ETHNICITY when 'H'

then count(STDM.student_id )

END )as Hispanic,

(CASE STDM.ETHNICITY when 'I'

then count(STDM.student_id )

END )as Indian,

(CASE STDM.ETHNICITY when 'M'

then count(STDM.student_id )

END )as Multiracial,

(CASE STDM.ETHNICITY when 'W'

then count(STDM.student_id )

END )as White

FROM STUDENT_DEMOGRAPHIC STDM

left join school_location SCH on STDM.school_number = SCH.S_SCHOOL_NUM

left join Meeting MTNG on STDM.student_id = MTNG.student_id

left join Meeting_Intervention MTGI on MTNG.Meeting_ID = MTGI.Meeting_ID

left join Intervention INTV on MTGI.Intervention_ID = INTV.Intervention_ID

where INTV.Intervention_ID not in ('')

group by SCHOOL_REGION,STDM.school_number,SCH.S_SCHL_NAME,Ethnicity

,INTV.Intervention_ID

ORDER BY SCHOOL_REGION,STDM.school_number,SCH.S_SCHL_NAME,Ethnicity

,INTV.Intervention_ID

P.S ...here the inner case statement is for the horizontal column names in the report

and I need the totals for the Type 1 ..type2 ...type 14 which is my vertical column in my report ( the INTV.Intervention_ID is this field) which i use in outer case statement above