繁体   English   中英

如何创建存储过程以递归计数许可证?

[英]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安装注册。

许可证是一种具有某些属性的事物:

  • 它用于特定的软件版本,例如“ Office 2007”或“ Windows 7”或“ Office 2010”或...等。
  • 它允许您运行特定数量的指定软件实例。
  • 在您的情况下,某些许可证可以代替其他许可证-例如,Office 2010许可证可用于Office 2007安装。

同样, 注册是一种具有某些属性的事物:

  • 它显示了执行安装时软件许可证的用法
  • 它显示安装在特定计算机上。

考虑到这些事实,我构造了一组表:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM