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.
Author |
Topic |
coolerbob
Aged Yak Warrior
841 Posts |
Posted - 2005-11-24 : 12:31:34
|
i have a problem where a sql script behaves one way but if i put that same code in a udf, it misbehaves and returns a different result.basically this query returns a bitmask that shows the combination of types that a contact at a company has been set tohere's the sql that works fine:CREATE TABLE [dbo].[mytbl] ( [mytype] [int] NULL , [marked] [bit] NULL ) ON [PRIMARY]GOALTER TABLE [dbo].[mytbl] ADD CONSTRAINT [DF_mytbl_mytype] DEFAULT (0) FOR [mytype], CONSTRAINT [DF_mytbl_marked] DEFAULT (0) FOR [marked]GO DECLARE @RowsAdded int declare @typ int declare @typbuf int set @typ = 0 set @typbuf = 0 set @RowsAdded = 0 insert mytbl(myType) select TYP_TypeEnum - 1000 --(the result of this is one of the follwing vals: 1,2,4,8,16,32,64) FROM Types INNER JOIN TypeLinks ON TYP_TypeID = CTS_TypeID INNER JOIN CompanyContacts ON CTS_ParentID = CON_ContactID where CON_ContactID = '3CF4C52C-298B-451E-9F71-2D43901B6C8F' SET @RowsAdded = @@rowcount WHILE @RowsAdded > 0 begin set @typbuf = (select top 1 myType from mytbl where Marked = 0) if @typbuf is null break SET @RowsAdded = @@rowcount set @typ = @typ | @typbuf update mytbl set Marked = 1 where myType = @typbuf endprint @typso there you go, that the sql statement that works fine. if i for example have a contact that has to typelinks records (say one is 1 and the other is 32), "print @typ" returns 33HOWEVER, do the same thing in a function, and the function returns 1 and not 33:create FUNCTION dbo.udf_gui_GetContactTypeBitMask(@contactGUID UNIQUEIDENTIFIER)returns intASBEGIN declare @tbl table (Typ int default 0, Marked bit default 0) DECLARE @RowsAdded int declare @typ int declare @typbuf int set @typ = 0 set @typbuf = 0 set @RowsAdded = 0 insert @tbl(Typ) select TYP_TypeEnum - 1000 FROM Types INNER JOIN TypeLinks ON TYP_TypeID = CTS_TypeID INNER JOIN CompanyContacts ON CTS_ParentID = CON_ContactID where CON_ContactID = @contactGUID SET @RowsAdded = @@rowcount WHILE @RowsAdded > 0 begin set @typbuf = (select top 1 Typ from @tbl where Marked = 0) if @typbuf is null break SET @RowsAdded = @@rowcount set @typ = @typ | @typbuf update @tbl set Marked = 1 where Typ = @typbuf end RETURN @typENDand then call it:select dbo.udf_gui_GetContactTypeBitMask('3CF4C52C-298B-451E-9F71-2D43901B6C8F')I've spent an hour on this, can any kind soul help? |
|
coolerbob
Aged Yak Warrior
841 Posts |
Posted - 2005-11-24 : 17:02:08
|
Sorry guys, I didnt give you enough info, can we try that again? I was talking rubbish as well. both cases below produce 1 as a result but I am after 33 as a result when I "or" the values. So it's got nothing to do with whether you use a function or a script. But debugging the script may be easier for you. I'm sure it's something dead simple. What am I missing?--ddlif exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[mytbl]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)drop table [dbo].[mytbl]GOif exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[CompanyContacts]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)drop table [dbo].[CompanyContacts]GOif exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[TypeLinks]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)drop table [dbo].[TypeLinks]GOif exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Types]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)drop table [dbo].[Types]GOCREATE TABLE [dbo].[TypeLinks] ( [CTS_TypeLinkID] uniqueidentifier ROWGUIDCOL NOT NULL , [CTS_TypeID] [uniqueidentifier] NOT NULL , [CTS_ParentID] [uniqueidentifier] NOT NULL ) ON [PRIMARY]GOCREATE TABLE [dbo].[Types] ( [TYP_TypeID] uniqueidentifier ROWGUIDCOL NOT NULL, [TYP_TypeEnum] [smallint] NOT NULL ) ON [PRIMARY]GOALTER TABLE [dbo].[TypeLinks] ADD CONSTRAINT [DF_TypeLinks_CTS_TypeLinkID] DEFAULT (newid()) FOR [CTS_TypeLinkID]GOALTER TABLE [dbo].[Types] ADD CONSTRAINT [DF_Types_TYP_TypeID] DEFAULT (newid()) FOR [TYP_TypeID]GOCREATE TABLE [dbo].[CompanyContacts] ( [CON_ContactID] [uniqueidentifier] NOT NULL) ON [PRIMARY]GOALTER TABLE [dbo].[CompanyContacts] ADD CONSTRAINT [DF_CompanyContacts_CON_ContactID] DEFAULT (newid()) FOR [CON_ContactID]GOCREATE TABLE [dbo].[mytbl] ([mytype] [int] NULL ,[marked] [bit] NULL ) ON [PRIMARY]GOALTER TABLE [dbo].[mytbl] ADD CONSTRAINT [DF_mytbl_mytype] DEFAULT (0) FOR [mytype],CONSTRAINT [DF_mytbl_marked] DEFAULT (0) FOR [marked]GO--test data---typesdeclare @a1 uniqueidentifierdeclare @a2 uniqueidentifierdeclare @a3 uniqueidentifierdeclare @a4 uniqueidentifierdeclare @a5 uniqueidentifierdeclare @a6 uniqueidentifierdeclare @a7 uniqueidentifierset @a1 = newid()set @a2 = newid()set @a3 = newid()set @a4 = newid()set @a5 = newid()set @a6 = newid()set @a7 = newid()insert into types select @a1,1insert into types select @a2,2insert into types select @a3,4insert into types select @a4,8insert into types select @a5,16insert into types select @a6,32insert into types select @a7,64--contactdeclare @c1 uniqueidentifierset @c1 = newid()insert into CompanyContacts select @c1--typelinksdeclare @t1 uniqueidentifierdeclare @t2 uniqueidentifierset @t1 = newid()set @t2 = newid()insert into typelinks select @t1,@a1,@c1insert into typelinks select @t2,@a6,@c1--sql script that prints "1" - but I'm trying to get it to register 33 because I want it to "OR" the valuesDECLARE @RowsAdded intdeclare @typ intdeclare @typbuf intset @typ = 0set @typbuf = 0set @RowsAdded = 0insert mytbl(myType)select TYP_TypeEnumFROM TypesINNER JOIN TypeLinks ON TYP_TypeID = CTS_TypeIDINNER JOIN CompanyContacts ON CTS_ParentID = CON_ContactIDwhere CON_ContactID = @c1SET @RowsAdded = @@rowcountWHILE @RowsAdded > 0beginset @typbuf = (select top 1 myType from mytbl where Marked = 0)if @typbuf is null breakSET @RowsAdded = @@rowcountset @typ = @typ | @typbufupdate mytbl set Marked = 1 where myType = @typbufendprint @typgo--same thing in a function, returns 1 and not 33:create FUNCTION dbo.udf_gui_GetContactTypeBitMask(@contactGUID UNIQUEIDENTIFIER)returns intASBEGINdeclare @tbl table (Typ int default 0, Marked bit default 0)DECLARE @RowsAdded intdeclare @typ intdeclare @typbuf intset @typ = 0set @typbuf = 0set @RowsAdded = 0insert @tbl(Typ)select TYP_TypeEnumFROM TypesINNER JOIN TypeLinks ON TYP_TypeID = CTS_TypeIDINNER JOIN CompanyContacts ON CTS_ParentID = CON_ContactIDwhere CON_ContactID = @contactGUIDSET @RowsAdded = @@rowcountWHILE @RowsAdded > 0beginset @typbuf = (select top 1 Typ from @tbl where Marked = 0)if @typbuf is null breakSET @RowsAdded = @@rowcountset @typ = @typ | @typbufupdate @tbl set Marked = 1 where Typ = @typbufendRETURN @typENDgo--and then call it:declare @c1 uniqueidentifierset @c1 = (select top 1 con_contactid from companycontacts)select dbo.udf_gui_GetContactTypeBitMask(@c1) |
|
|
coolerbob
Aged Yak Warrior
841 Posts |
Posted - 2005-11-24 : 17:19:21
|
Well well well, what do we have here??? It appears I have a solution that envolves CURSORS Any Master based sets out there care to show me how to do this without one? (jokes aside, this is a "production" query and I don't REALLY want to leave the cursor code in there...)Runn this against the DDL provided previously:create FUNCTION dbo.udf_gui_GetContactTypeBitMask(@contactGUID UNIQUEIDENTIFIER)returns intASBEGIN declare @tbl table (Typ int default 0, Marked bit default 0) DECLARE @RowsAdded int declare @typ int declare @typbuf int set @typ = 0 set @typbuf = 0 set @RowsAdded = 0 insert @tbl(Typ) select TYP_TypeEnum - 1000 FROM Types INNER JOIN TypeLinks ON TYP_TypeID = CTS_TypeID INNER JOIN CompanyContacts ON CTS_ParentID = CON_ContactID where CON_ContactID = @contactGUIDDECLARE _Cursor CURSOR FORSELECT Typ from @tblOPEN _Cursordeclare @T_typ intFETCH NEXT FROM _Cursor INTO @T_typWHILE @@FETCH_STATUS = 0 BEGIN set @typ = @typ | @T_typ FETCH NEXT FROM _Cursor INTO @T_typENDCLOSE _CursorDEALLOCATE _Cursor RETURN @typEND |
|
|
nr
SQLTeam MVY
12543 Posts |
Posted - 2005-11-24 : 19:10:27
|
think you can replace the cursor withselect @typ = 0select @typ = @typ | Typ from @tblor evenselect @typ = 0select @typ = @typ | (TYP_TypeEnum - 1000)FROM TypesINNER JOIN TypeLinks ON TYP_TypeID = CTS_TypeIDINNER JOIN CompanyContacts ON CTS_ParentID = CON_ContactIDwhere CON_ContactID = @contactGUID==========================================Cursors are useful if you don't know sql.DTS can be used in a similar way.Beer is not cold and it isn't fizzy. |
|
|
coolerbob
Aged Yak Warrior
841 Posts |
Posted - 2005-11-24 : 21:07:48
|
does it ever get boring to be so clever? |
|
|
|
|
|
|
|