简体   繁体   English

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

[英]How to create a Stored Procedure to count licences recursively?

I have only a very little experience with SQL and now i'm stuck. 我对SQL的经验很少,但现在遇到了麻烦。

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. 我阅读了此注册表项,然后将其插入到SQL数据库中。

My Licences table has the following columns. 我的许可证表包含以下列。
- PackageName - 包裹名字
- DisplayName - 显示名称
- Bought -买了
- Free - 自由
- SubstituteLicense -替代许可证
- Custom -自定义

The problem is with this SubstitueLicense. 问题在于此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. 如果记录的替代许可证的值为Free,并且Free为0,则应减少替代许可证的Free值。 I made a stored procedure which works fine if substitulicense has no value, but i don't know how to do the rest. 我制作了一个存储过程,如果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

Could someone help me to solve this? 有人可以帮我解决这个问题吗?

Thanks! 谢谢!

Update: 更新:

Sorry i forgot to tell, that substitulicense is nvarchar type. 对不起,我忘了告诉我们,替代许可是nvarchar类型。 It contains another package name. 它包含另一个软件包名称。 I need this, because for example we have 100 pcs Office 2007 Licences and 50 pcs Office 2010 Licences. 我需要这个,因为例如我们有100个Office 2007许可证和50个Office 2010许可证。 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. 但是Office 2010许可证也可以用于Office 2007,因此我们可以使用150个Office2007。当然,该表中还存在packaga替代授权值,该值是我要减少的值。 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. 我认为您遇到的部分困难(尤其是递归计数-如果您要逐行尝试在SQL中执行某些操作,则这是一个很好的指标,您可能希望了解一下自己的方式建物)与数据库的结构有关。

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. 您试图做的是建立一个经典的资源分配跟踪器-如果您有10个Office 2007许可证,则要跟踪注册了哪些计算机才能使用这些许可证。 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. 请考虑以下有关该问题的事实:您具有要跟踪的X许可证和Y安装注册。

A license is a type of thing which has certain properties: 许可证是一种具有某些属性的事物:

  • It is for a specific software version, like 'Office 2007' or 'Windows 7' or 'Office 2010' or... etc. 它用于特定的软件版本,例如“ Office 2007”或“ Windows 7”或“ Office 2010”或...等。
  • It allows you to run a specific number of instances of the specified software. 它允许您运行特定数量的指定软件实例。
  • In your case, certain kinds of licenses are allowed to substitute for other licenses - for example, Office 2010 licenses can be used for Office 2007 installations. 在您的情况下,某些许可证可以代替其他许可证-例如,Office 2010许可证可用于Office 2007安装。

A registration is, again, a type of thing with certain properties: 同样, 注册是一种具有某些属性的事物:

  • It shows the usage of a software license when performing an installation 它显示了执行安装时软件许可证的用法
  • It shows that the install is on a specific machine. 它显示安装在特定计算机上。

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'. 在这种情况下,此表中的每一行都显示“允许此License_ID代替指定的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: 让我们以您提到的两个许可证(Office 2007和Office 2010)并将它们放入“许可证”表中为例:

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: 根据您的规则,我们还知道2010许可证可以代替2007许可证,因此License_Substitutes看起来像:

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: 如果要在我的计算机上注册2007年的副本,则注册将类似于:

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. Substitute_License保留为NULL,因为该注册不需要替代。

However, let's say that you now install 2007 on your computer. 但是,假设您现在在计算机上安装了2007。 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). 此处的Substitute_License记录为2(对于Office 2010)。 License_Substitutes.Substitute_ID is just an identity value to keep rows distinct. License_Substitutes.Substitute_ID只是一个标识值,用于使行保持不同。

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: 假设SubstitueLicense为整数类型:

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 那应该满足您的要求: 如果记录的替代许可证的值为Free,而Free为0,则应减小替代许可证的Free值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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