Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 SPs ot Triggers

Author  Topic 

viketo
Starting Member

1 Post

Posted - 2004-07-17 : 04:50:17
Hi all,

I hesitate what to use SPs or triggers. I would like my queries to be as fast as possible. My data base is something like this:

UsersTable
------------
UserID(PK) | UserName | Password | Name | Addr | E-mail | UsrType | Role | LastLogOn

EstatesTbale
-----------
EstateID(PK) City Phone Heating Furniture TypeEstate(FK) TypeOffr(FK) TypeConstr(FK)

OfferTable
------------
EstateID(FK) UserID(FK) Value ParamID(FK)

Param Table
--------------
ParamID(PK) Param

TypeEstateTable
----------------
Unikey(PK) TypeEstate

TypeOFFRTable
-------------
Unikey(PK) TypeOffr

TypeConstr
-------------
Unikey(PK) TypeConstr

PictureEstateTable
---------------------
ID(PK) EstateID(FK) PictureFilePath

DescriptionEstateTable
-------------------------
ID(PK) EstateID(FK) TextDescription


I develop Web based application using ASP.NET/C#/MS SQL. I'd like to ask you would you change something in the tables? And also, I would like what would be better:
1. To import user data by registration whit SP or Trigger?
2. When a registrated user would like to place an Advertisement what would be better again stored procedure or trigger?
For this inserting I wrote my first SP:

CREATE PROCEDURE prSVOFFRDATA
@CITY VARCHAR(20),
@PHONE CHAR(1), -- Insert 'Y' or 'N'
@FURN CHAR(1), -- Insert 'Y' or 'N'
@HEATING CHAR(1), -- Insert 'Y' or 'N'
@TYPEESTATE CHAR(3),
@TYPEOFFR INT,
@TYPECONSTR CHAR(1),
@USERID INT,
@ValuePrice BIGINT,
@ValueFloor BIGINT,
@ValueArea BIGINT,
@ValueRooms BIGINT,
@PICTURE VARCHAR(50),
@DESCRIPTION VARCHAR(255)

AS
INSERT INTO BLEK.EstatesTable(City,Phone,Furn,Heating,TypeEstate,TypeOffr,TypeConstr)
VALUES(@CITY,@PHONE,@FURN,@HEATING,@TYPEESTATE,@TYPEOFFR,@TYPECONSTR)
DECLARE @IDENT INT
SELECT @IDENT = SCOPE_IDENTITY()
INSERT INTO BLEK.OFFERTABLE(EstateID,UserID,Value,ParamID)
VALUES(@IDENT,@USERID,@ValuePrice,'price')
INSERT INTO BLEK.OFFERTABLE(EstateID,UserID,Value,ParamID)
VALUES(@IDENT,@USERID,@ValueFloor,'floor')
INSERT INTO BLEK.OFFERTABLE(EstateID,UserID,Value,ParamID)
VALUES(@IDENT,@USERID,@ValueArea,'area')
INSERT INTO BLEK.OFFERTABLE(EstateID,UserID,Value,ParamID)
VALUES(@IDENT,@USERID,@ValueRooms,'room')

IF (@PICTURE IS NOT NULL)
INSERT INTO BLEK.PICTUREESTATETABLE(EstateID,PICTUREFILEPATH) VALUES(@IDENT,@PICTURE)
IF (@DESCRIPTION IS NOT NULL)
INSERT INTO BLEK.DSCRIPTIONESTATETABLE(EstateID,TextDescription) VALUES(@IDENT,@DESCRIPTION)

You can see that it is my first SP:) I dont know how to optimize it. I don't have an idea would be better if I CREATE VIEW and use TRIGGER to populate data in the tables. I have to UPDATE this rows when a user wants to change the data in his/her advertisement.
I have also a big SEARCH query between 4 tables. What would you mean? To CREATE VIEW and to use SELCT QUERY from this VIEW or to create Stored PRocedure.
Could help me please, could you give me an advice?

Thank you very much!

kselvia
Aged Yak Warrior

526 Posts

Posted - 2004-07-17 : 05:24:25
A lot of good questions. Many different good answers. A few quick observations:

Put all declarations at the beginning of procedures. SQL sometimes has to recompile query plans when they occur in the middle of the procedure

DECLARE @IDENT INT

INSERT INTO BLEK.EstatesTable(City,Phone,Furn,Heating,TypeEstate,TypeOffr,TypeConstr)
VALUES(@CITY,@PHONE,@FURN,@HEATING,@TYPEESTATE,@TYPEOFFR,@TYPECONSTR)
SELECT @IDENT = SCOPE_IDENTITY()

-- You can insert all rows into Offertable at once like this:

INSERT INTO BLEK.OFFERTABLE(EstateID,UserID,Value,ParamID)
SELECT @IDENT,@USERID,@ValuePrice,'price' UNION ALL
SELECT @IDENT,@USERID,@ValueFloor,'floor' UNION ALL
SELECT @IDENT,@USERID,@ValueArea,'area' UNION ALL
SELECT @IDENT,@USERID,@ValueRooms,'room'


If your search from 4 tables will have different search criteria you want a stored procedure, but there are about 5 differnt ways to implement that as well. See this article for a description of some of the methods: [url]http://www.sqlteam.com/item.asp?ItemID=2077[/url]


--Ken
Your Kung-Fu is not strong. -- 'The Core'
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2004-07-17 : 07:50:07
In case it is helpful I have reformatted your SProc, with Ken's suggestions, as I would write it.

PRINT 'Create procedure prSVOFFRDATA'
GO
IF EXISTS (SELECT * FROM sysobjects WHERE id = object_id(N'[dbo].[prSVOFFRDATA]')
AND OBJECTPROPERTY(id, N'IsProcedure') = 1)
BEGIN
DROP PROCEDURE dbo.prSVOFFRDATA
END
GO
CREATE PROCEDURE dbo.prSVOFFRDATA
@CITY VARCHAR(20),
@PHONE CHAR(1), -- Insert 'Y' or 'N'
@FURN CHAR(1), -- Insert 'Y' or 'N'
@HEATING CHAR(1), -- Insert 'Y' or 'N'
@TYPEESTATE CHAR(3),
@TYPEOFFR INT,
@TYPECONSTR CHAR(1),
@USERID INT,
@ValuePrice BIGINT,
@ValueFloor BIGINT,
@ValueArea BIGINT,
@ValueRooms BIGINT,
@PICTURE VARCHAR(50),
@DESCRIPTION VARCHAR(255)

AS
SET NOCOUNT ON
SET XACT_ABORT ON -- Force this SProc to abort if runtime errors occur

DECLARE @IDENT INT,
@intErrNo INT,
@intRowCount INT,
@intFailPoint INT -- Indicates "where" any error occurred

SELECT @intErrNo = 0 -- Assume no error

-- Tidy up data
SELECT @PHONE = UPPER(@PHONE),
@FURN = UPPER(@FURN),
@HEATING = UPPER(@HEATING)

-- Validate data
IF @PHONE NOT IN ('Y', 'N')
BEGIN
SELECT @intFailPoint = -1,
@intErrNo = -999
GOTO prSVOFFRDATA_Exit
END

... other validation here ...

BEGIN TRANSACTION


INSERT INTO BLEK.EstatesTable(City, Phone, Furn, Heating, TypeEstate,
TypeOffr, TypeConstr)
VALUES(@CITY, @PHONE, @FURN, @HEATING, @TYPEESTATE, @TYPEOFFR, @TYPECONSTR)
SELECT @IDENT = SCOPE_IDENTITY(), @intErrNo = @@ERROR, @intRowCount = @@ROWCOUNT,
@intFailPoint=1
IF @intErrNo <> 0 OR @intRowCount <> 1 GOTO prSVOFFRDATA_Abort


-- You can insert all rows into Offertable at once like this:

INSERT INTO BLEK.OFFERTABLE(EstateID, UserID, Value, ParamID)
SELECT @IDENT, @USERID, @ValuePrice, 'price'
UNION ALL SELECT @IDENT, @USERID, @ValueFloor, 'floor'
UNION ALL SELECT @IDENT, @USERID, @ValueArea, 'area'
UNION ALL SELECT @IDENT, @USERID, @ValueRooms, 'room'
SELECT @intErrNo = @@ERROR, @intRowCount = @@ROWCOUNT, @intFailPoint=2
IF @intErrNo <> 0 OR @intRowCount <> 1 GOTO prSVOFFRDATA_Abort


IF (@PICTURE IS NOT NULL)
BEGIN
INSERT INTO BLEK.PICTUREESTATETABLE(EstateID, PICTUREFILEPATH)
VALUES(@IDENT, @PICTURE)
SELECT @intErrNo = @@ERROR, @intRowCount = @@ROWCOUNT, @intFailPoint=3
IF @intErrNo <> 0 OR @intRowCount <> 1 GOTO prSVOFFRDATA_Abort
END

IF (@DESCRIPTION IS NOT NULL)
BEGIN
INSERT INTO BLEK.DSCRIPTIONESTATETABLE(EstateID, TextDescription)
VALUES(@IDENT, @DESCRIPTION)
SELECT @intErrNo = @@ERROR, @intRowCount = @@ROWCOUNT, @intFailPoint=4
IF @intErrNo <> 0 OR @intRowCount <> 1 GOTO prSVOFFRDATA_Abort
END


prSVOFFRDATA_Abort:
IF @intErrNo = 0
BEGIN
COMMIT TRANSACTION
END
ELSE
BEGIN
ROLLBACK TRANSACTION
END

prSVOFFRDATA_Exit:
IF @intErrNo = 0
BEGIN

-- Report error to User/Application some how
-- [output variable / select list / LOG table / RAISERROR() ...]
SELECT 'prSVOFFRDATA failed with error ['
+ CONVERT(varchar(20), @intErrNo)
+'] processing ['
+ CONVERT(varchar(20), @intRowCount)
+'] at FailPoint ['
+ CONVERT(varchar(20), @intFailPoint)
+']' AS ErrorMessage,
@CITY AS [@CITY],
@PHONE AS [@PHONE],
@FURN AS [@FURN],
@HEATING AS [@HEATING],
@TYPEESTATE AS [@TYPEESTATE],
@TYPEOFFR AS [@TYPEOFFR],
@TYPECONSTR AS [@TYPECONSTR],
@USERID AS [@USERID],
@ValuePrice AS [@ValuePrice],
@ValueFloor AS [@ValueFloor],
@ValueArea AS [@ValueArea],
@ValueRooms AS [@ValueRooms],
@PICTURE AS [@PICTURE],
@DESCRIPTION AS [@DESCRIPTION]
END
SET NOCOUNT OFF
RETURN @intErrNo -- 0=No error
/* TEST RIG
BEGIN TRANSACTION
EXEC dbo.prSVOFFRDATA
@CITY = 'MyCity',
@PHONE 'Y',
@FURN 'Y',
@HEATING 'N',
@TYPEESTATE 'FOO',
@TYPEOFFR 1,
@TYPECONSTR 'X',
@USERID 1234,
@ValuePrice 11234567890,
@ValueFloor 21234567890,
@ValueArea 31234567890,
@ValueRooms 41234567890,
@PICTURE 'FooBar.JPG',
@DESCRIPTION 'Des Res'
ROLLBACK

*/
--================== rk_SP_XX_ModuleDetail_Get ==================--
GO
IF exists (SELECT * FROM sysobjects WHERE id = object_id(N'[dbo].[prSVOFFRDATA]')
AND OBJECTPROPERTY(id, N'IsProcedure') = 1)
BEGIN
GRANT EXECUTE ON dbo.prSVOFFRDATA TO MyPermissionsRole
END
GO
PRINT 'Create procedure prSVOFFRDATA DONE'
GO


Do you have a good reason for using the Owner "BLEK"? Having everything owned by "dbo" makes life much easier :)

I, personally, would capitalise the Parameters exactly the same as the columns to which they refer - also, you have the parameter @PICTURE which goes in the column PICTUREFILEPATH - I would make them the same, and change the column name to PictureFilePath.

I have included a TRANSACTION block. If any errors occur during the INSERTs then the transaction will be ROLLBACK'd - i.e. NONE of the inserts will exist. This will keep the database "tidy".

I've put put some checks at the very top of the SProc to Validate Data Quality.

I have done an error check after each statement; I have used a variable @intFailPoint, set to a number that is unique within the SProc. If it fails, and reports FailPoint=4 you can more easily work out where it went wrong.

The TEST RIG contains one, or more, examples that have been used in testing and is intended to allow any modifications to be quickly re-tested

Kristen
Go to Top of Page
   

- Advertisement -