I have only a very little experience with SQL and now i'm stuck.
So what i want is the following. We make installation packages, to install applications preconfigured. These packages will create a registry entry with the application's name. I read this registry entries and then i'm inserting it into an SQL database.
My Licences table has the following columns.
- PackageName
- DisplayName
- Bought
- Free
- SubstituteLicense
- Custom
The problem is with this SubstitueLicense. So i want to make a stored procedure which should work in the following way. If a record's substitutelicense has a value and Free is 0, then the substitulicense's Free value should be decremented. I made a stored procedure which works fine if substitulicense has no value, but i don't know how to do the rest.
USE [HWSW_Inventory]
GO
/****** Object: StoredProcedure [dbo].[InsertWrapAppAndDecrementLicence] Script Date: 12/30/2011 22:45:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[InsertWrapAppAndDecrementLicence]
-- Add the parameters for the stored procedure here
@String varchar( 8000 ),
@HostName varchar( 50 )
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
declare @LineIdx int
declare @PackageIdx int
declare @Line varchar( 8000 )
declare @InsertValues varchar( 4000 )
declare @PackageName varchar( 200 )
declare @Command varchar( 8000 )
select @LineIdx = 1
if ( ( len( @String ) < 1 ) or ( @String is null ) ) return
while ( @LineIdx != 0 )
begin
--set LineIdx to the first occurence of a line separator
set @LineIdx = charindex( ';', @String )
if ( @LineIdx != 0 ) set @Line = left( @String, @LineIdx - 1 )
else set @Line = @String
--replace value delimeters and concatenate the hostname so we have a string what we can insert into the database
set @InsertValues = '''' + REPLACE( @Line, '|', ''', ''') + ''', ''' + @HostName + ''''
--get the first occurence of a ',' from the string what we want to insert, because it is the PackageName
set @PackageIdx = CHARINDEX( '|', @String )
if ( @PackageIdx != 0 ) set @PackageName = left( @String, @PackageIdx - 1 )
else set @PackageName = @String
set @Command = 'insert into dbo.WrapperApplications values ( ' + @InsertValues + ' )'
exec ( @Command )
update Licences set Free = Free - 1 where ( Licences.PackageName = @PackageName )
set @String = right( @String, len( @String ) - @LineIdx )
if ( len( @String ) = 0 ) break
end--while
END--main
Could someone help me to solve this?
Thanks!
Update:
Sorry i forgot to tell, that substitulicense is nvarchar type. It contains another package name. I need this, because for example we have 100 pcs Office 2007 Licences and 50 pcs Office 2010 Licences. But Office 2010 licences can be used for office 2007 too, and so we can use 150 pcs of Office 2007. Of course the packaga what substitilicense value is exists also in this table, and this value is what i want to decrement. Hope you understand now how i meant
I think part of the difficulty you're having (especially with recursive counting - if you're trying to do something in SQL on a row-by-row basis, that's a good indicator that you might want to look at the way you've built things) is related to how your database is structured.
What you're attempting to do is build a classic resource allocation tracker - if you have 10 licenses for Office 2007, you want to keep track of which computers are registered to use those licenses. Having more active software registrations than you have licenses is a recipe for trouble.
Consider the following facts about the problem: You have X licenses and Y installed registrations that you want to keep track of.
A license is a type of thing which has certain properties:
A registration is, again, a type of thing with certain properties:
With these facts in mind, I constructed a set of tables:
Licenses:
License_ID integer identity(1,1)
Package_Name varchar( 200 )
Display_Name varchar( 400 )
Bought integer
The above table just holds the information about each license type.
License_Substitutes:
Substitute_ID integer identity(1,1)
License_ID integer
Allowed_Sub_License integer
This table contains information about relationships between different licences; in this case, each row in this table says 'this License_ID is allowed to substitute for the specified Allowed_Sub_License'.
Registrations:
Registration_ID integer identity(1,1)
Installed_License integer
Substitute_License integer
Description varchar(80)
If you have other information in your registry entry that I'm not aware of (like who the registration is for, where or what computers, etc.) columns in this table would be the best way to store that data.
Let's take the two licenses you mentioned (Office 2007 and Office 2010) and put them into the Licenses table:
License_ID Package_Name Display_Name Bought
1 Off2007 Microsoft Office 2007 1
2 Off2010 Microsoft Office 2010 1
We've just bought one copy of each, nothing special. Given your rules, we also know that a 2010 license can substitute for a 2007 license, so License_Substitutes looks like:
Substitute_ID License_ID Allowed_Sub_License
1 2 1
Once the licenses have been entered and the substitution relationships have been determined, you can register software using those licenses. If you were to register a copy of 2007 on my computer, Registrations would look like:
Registration_ID Installed_License Substitute_License Description
1 1 NULL Mikurski's computer
Substitute_License is left NULL as that registration does not need a substitute.
However, let's say that you now install 2007 on your computer. Registrations would look like:
Registration_ID Installed_License Substitute_License Description
1 1 NULL Mikurski's computer
1 1 2 kampi's computer
Substitute_License here is recorded as 2 (for Office 2010). License_Substitutes.Substitute_ID is just an identity value to keep rows distinct.
You'll notice that 'Free' is not here as a column anymore. This is because the number of free spots for a license can be calculated in a query:
select count(*) from Registrations
where (installed_license = @Your_License_ID and substitute_license is NULL)
or substitute_license = @Your_License_ID
Normalizing the database like this (for more information about normalization, I've found this to be a good introduction) helps minimize the amount of upkeep work you have to put into maintaining data integrity, and means the database will be easier to extend if your needs change in the future.
Assuming SubstitueLicense is of type integer:
update
Licences set Free = Free - 1
where
(
Licences.PackageName = @PackageName and
Licenses.SubstitueLicese > 0 and
Licenses.Free = 0
)
That should meet your requirement: If a record's substitutelicense has a value and Free is 0, then the substitulicense's Free value should be decremented
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.