| 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 | LastLogOnEstatesTbale-----------EstateID(PK) City Phone Heating Furniture TypeEstate(FK) TypeOffr(FK) TypeConstr(FK)OfferTable------------EstateID(FK) UserID(FK) Value ParamID(FK)Param Table--------------ParamID(PK) ParamTypeEstateTable----------------Unikey(PK) TypeEstateTypeOFFRTable-------------Unikey(PK) TypeOffrTypeConstr-------------Unikey(PK) TypeConstrPictureEstateTable---------------------ID(PK) EstateID(FK) PictureFilePathDescriptionEstateTable-------------------------ID(PK) EstateID(FK) TextDescriptionI 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)ASINSERT INTO BLEK.EstatesTable(City,Phone,Furn,Heating,TypeEstate,TypeOffr,TypeConstr) VALUES(@CITY,@PHONE,@FURN,@HEATING,@TYPEESTATE,@TYPEOFFR,@TYPECONSTR)DECLARE @IDENT INTSELECT @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 procedureDECLARE @IDENT INTINSERT 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]--KenYour Kung-Fu is not strong. -- 'The Core' |
 |
|
|
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'GOIF EXISTS (SELECT * FROM sysobjects WHERE id = object_id(N'[dbo].[prSVOFFRDATA]') AND OBJECTPROPERTY(id, N'IsProcedure') = 1)BEGIN DROP PROCEDURE dbo.prSVOFFRDATAENDGOCREATE 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)ASSET NOCOUNT ONSET XACT_ABORT ON -- Force this SProc to abort if runtime errors occurDECLARE @IDENT INT, @intErrNo INT, @intRowCount INT, @intFailPoint INT -- Indicates "where" any error occurredSELECT @intErrNo = 0 -- Assume no error-- Tidy up dataSELECT @PHONE = UPPER(@PHONE), @FURN = UPPER(@FURN), @HEATING = UPPER(@HEATING)-- Validate dataIF @PHONE NOT IN ('Y', 'N')BEGIN SELECT @intFailPoint = -1, @intErrNo = -999 GOTO prSVOFFRDATA_ExitEND... other validation here ...BEGIN TRANSACTIONINSERT 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=1IF @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=2IF @intErrNo <> 0 OR @intRowCount <> 1 GOTO prSVOFFRDATA_AbortIF (@PICTURE IS NOT NULL)BEGININSERT INTO BLEK.PICTUREESTATETABLE(EstateID, PICTUREFILEPATH) VALUES(@IDENT, @PICTURE)SELECT @intErrNo = @@ERROR, @intRowCount = @@ROWCOUNT, @intFailPoint=3IF @intErrNo <> 0 OR @intRowCount <> 1 GOTO prSVOFFRDATA_AbortENDIF (@DESCRIPTION IS NOT NULL)BEGININSERT INTO BLEK.DSCRIPTIONESTATETABLE(EstateID, TextDescription) VALUES(@IDENT, @DESCRIPTION)SELECT @intErrNo = @@ERROR, @intRowCount = @@ROWCOUNT, @intFailPoint=4IF @intErrNo <> 0 OR @intRowCount <> 1 GOTO prSVOFFRDATA_AbortENDprSVOFFRDATA_Abort:IF @intErrNo = 0BEGIN COMMIT TRANSACTIONENDELSEBEGIN ROLLBACK TRANSACTIONENDprSVOFFRDATA_Exit:IF @intErrNo = 0BEGIN-- 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]ENDSET NOCOUNT OFFRETURN @intErrNo -- 0=No error/* TEST RIGBEGIN TRANSACTIONEXEC 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 ==================--GOIF exists (SELECT * FROM sysobjects WHERE id = object_id(N'[dbo].[prSVOFFRDATA]') AND OBJECTPROPERTY(id, N'IsProcedure') = 1)BEGIN GRANT EXECUTE ON dbo.prSVOFFRDATA TO MyPermissionsRoleENDGOPRINT 'Create procedure prSVOFFRDATA DONE'GODo 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-testedKristen |
 |
|
|
|
|
|