[英]How to create a Stored Procedure to count licences recursively?
我对SQL的经验很少,但现在遇到了麻烦。
所以我想要的是以下内容。 我们制作安装包,以安装预先配置的应用程序。 这些软件包将使用应用程序的名称创建一个注册表项。 我阅读了此注册表项,然后将其插入到SQL数据库中。
我的许可证表包含以下列。
- 包裹名字
- 显示名称
-买了
- 自由
-替代许可证
-自定义
问题在于此SubstitueLicense。 所以我想做一个存储过程,该过程应按以下方式工作。 如果记录的替代许可证的值为Free,并且Free为0,则应减少替代许可证的Free值。 我制作了一个存储过程,如果substitulicense没有价值,它可以正常工作,但是我不知道如何做其余的工作。
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
有人可以帮我解决这个问题吗?
谢谢!
更新:
对不起,我忘了告诉我们,替代许可是nvarchar类型。 它包含另一个软件包名称。 我需要这个,因为例如我们有100个Office 2007许可证和50个Office 2010许可证。 但是Office 2010许可证也可以用于Office 2007,因此我们可以使用150个Office2007。当然,该表中还存在packaga替代授权值,该值是我要减少的值。 希望你现在明白我的意思
我认为您遇到的部分困难(尤其是递归计数-如果您要逐行尝试在SQL中执行某些操作,则这是一个很好的指标,您可能希望了解一下自己的方式建物)与数据库的结构有关。
您试图做的是建立一个经典的资源分配跟踪器-如果您有10个Office 2007许可证,则要跟踪注册了哪些计算机才能使用这些许可证。 具有比您的许可证更多的活动软件注册是麻烦的根源。
请考虑以下有关该问题的事实:您具有要跟踪的X许可证和Y安装注册。
许可证是一种具有某些属性的事物:
同样, 注册是一种具有某些属性的事物:
考虑到这些事实,我构造了一组表:
Licenses:
License_ID integer identity(1,1)
Package_Name varchar( 200 )
Display_Name varchar( 400 )
Bought integer
上表仅包含有关每种许可证类型的信息。
License_Substitutes:
Substitute_ID integer identity(1,1)
License_ID integer
Allowed_Sub_License integer
该表包含有关不同许可证之间关系的信息; 在这种情况下,此表中的每一行都显示“允许此License_ID代替指定的Allowed_Sub_License”。
Registrations:
Registration_ID integer identity(1,1)
Installed_License integer
Substitute_License integer
Description varchar(80)
如果您的注册表项中还有其他我不知道的信息(例如,谁在注册,在哪里或在什么计算机等),则此表中的列将是存储该数据的最佳方法。
让我们以您提到的两个许可证(Office 2007和Office 2010)并将它们放入“许可证”表中为例:
License_ID Package_Name Display_Name Bought
1 Off2007 Microsoft Office 2007 1
2 Off2010 Microsoft Office 2010 1
我们只买了一份,没什么特别的。 根据您的规则,我们还知道2010许可证可以代替2007许可证,因此License_Substitutes看起来像:
Substitute_ID License_ID Allowed_Sub_License
1 2 1
输入许可证并确定替换关系后,即可使用这些许可证注册软件。 如果要在我的计算机上注册2007年的副本,则注册将类似于:
Registration_ID Installed_License Substitute_License Description
1 1 NULL Mikurski's computer
Substitute_License保留为NULL,因为该注册不需要替代。
但是,假设您现在在计算机上安装了2007。 注册看起来像:
Registration_ID Installed_License Substitute_License Description
1 1 NULL Mikurski's computer
1 1 2 kampi's computer
此处的Substitute_License记录为2(对于Office 2010)。 License_Substitutes.Substitute_ID只是一个标识值,用于使行保持不同。
您会注意到“免费”不再在此处作为列。 这是因为可以在查询中计算许可证的可用点数:
select count(*) from Registrations
where (installed_license = @Your_License_ID and substitute_license is NULL)
or substitute_license = @Your_License_ID
这样对数据库进行规范化(有关规范化的更多信息,我发现这是一个不错的介绍)有助于最大程度地减少维护数据完整性所需的维护工作量,并且如果您的数据库更易于扩展,未来需要改变。
假设SubstitueLicense为整数类型:
update
Licences set Free = Free - 1
where
(
Licences.PackageName = @PackageName and
Licenses.SubstitueLicese > 0 and
Licenses.Free = 0
)
那应该满足您的要求: 如果记录的替代许可证的值为Free,而Free为0,则应减小替代许可证的Free值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.