数据库,关系查询

时间:2016-02-27 09:29:37

标签: database search autoit

化学品具有商品名称(通常称为)和实际的化学名称。我需要查找商品名称,找到其正确的化学名称,然后获得该化学品的属性。例如:

$tradeName = "Voranol"

if $tradeName == "Voranol" then
    $productName = "Polyether Polyol"
    $flare = "List I"
    $bay = "1"
    $listPos = 3
EndIf

我有一个包含大量产品的.au3文件。它工作正常,但if $tradeName == "Name1" or $tradeName == "Name2" or $tradeName == "Name4" or $tradeName == "Name5"有点乏味。我还需要能够以编程方式编辑它。这就是我现在正在使用的:

if $product == "dowanol pmb" or $product == "dowanol pma" or $product == "dipropylene glycol" or $product == "dowanol pnp" or $productCheck2 == "dowanol pmb" or $productCheck2 == "dowanol pma" or $productCheck2 == "dipropylene glycol" or $productCheck2 == "dowanol pnp" then
    $result = "DIPROPYLENE GLYCOL"
    $bay = 4
    $useFlare = 1
    $listPos = 2

elseif $product == "glycol blend" then
    $result = "GLYCOL"
    $bay = 3
    $useFlare = 2
    $listPos = 1

elseif $product == "isopar e" or $product == "isopar c" or $product == "isopar h" or $productCheck2 == "isopar h" then
    $result = "PETROLEUM NAPTHA"
    $bay = 5
    $useFlare = 0
    $listPos = 1 

EndIf
; Note: 0 = No Flare, 1 = Normal Flare, 2 = CAS Flare

3 个答案:

答案 0 :(得分:5)

数据库选项的另一种替代方法是使用XML文档来存储产品(化学品)信息。

您可以使用XPath轻松查询XML以获取产品名称/属性。维护文件也很容易。您甚至可以创建一个XML Schema进行验证,以确保您的文件在修改后仍然有效。

AutoIt中的XML处理可以通过几种不同的方式完成:

  • 创建MSXML对象
  • 运行xmlstarlet
  • 等命令行工具
  • 从命令行使用XPath / XQuery / XSLT处理器(即java运行Saxon

像萨克森这样的运行对你所需要的东西来说可能有些过分。

MSXML不会太糟糕,应该有多个已经存在的UDF。

Xmlstarlet将是我的投票。 (注意:我以前没有以这种方式使用过xmlstarlet。我是Saxon的忠实粉丝并且几乎专门使用它。特别是对于AutoIt,我使用了MSXML和Saxon的组合; Saxon用于复杂的转换将数据转换为更小,更简单的子集,然后使用MSXML对该子集进行简单的xpath查询。但是,如果我要做这样的事情,我会认真对待xmlstarlet。)

此外,如果您的数据增长到单个XML文件没有意义的程度,您可以随时将其拆分为较小文件的集合;个别产品也许。您可能还会指出将这些文件加载​​到实际的XML数据库中是有意义的(eXistdb是一个选项)。

以下是XML(架构和实例)的简单示例:

XSD (products.xsd)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="products">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" ref="product"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="product">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="name"/>
        <xs:element ref="tradenames"/>
      </xs:sequence>
      <xs:attribute name="bay" use="required" type="xs:integer"/>
      <xs:attribute name="listpos" use="required" type="xs:integer"/>
      <xs:attribute name="useflare" use="required" type="xs:integer"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="tradenames">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" ref="name"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="name" type="xs:string"/>
</xs:schema>

XML (products.xml)

<products xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="products.xsd">
    <product bay="4" useflare="1" listpos="2">
        <name>DIPROPYLENE GLYCOL</name>
        <tradenames>
            <name>dowanol pmb</name>
            <name>dowanol pma</name>
            <name>dipropylene glycol</name>
            <name>dowanol pnp</name>
        </tradenames>
    </product>
    <product bay="3" useflare="2" listpos="1">
        <name>GLYCOL</name>
        <tradenames>
            <name>glycol blend</name>
        </tradenames>
    </product>
    <product bay="5" useflare="0" listpos="1">
        <name>PETROLEUM NAPTHA</name>
        <tradenames>
            <name>isopar e</name>
            <name>isopar c</name>
            <name>isopar h</name>
        </tradenames>
    </product>
</products>

这里有一点AutoIt,它使用MSXML演示加载XML(针对XSD验证)并搜索商品名称包含“乙二醇”的产品。

<强>的AutoIt

;~  AutoIt Version: 3.3.14.2

;String to search on.
$searchString = "glycol"
ConsoleWrite("Search string: '" & $searchString & "'" & @CRLF)

;XPath for searching trade names. Search string is injected (code injection; escaping of strings would be a very good idea!).
$xpath_tradename = "/products/product[tradenames/name[contains(.,'" & $searchString & "')]]"
ConsoleWrite("XPath: '" & $xpath_tradename & "'" & @CRLF)

$msxml = ObjCreate('MSXML2.DOMDocument.6.0')
If IsObj($msxml) Then
    $msxml.async = False
    $msxml.validateOnParse = True
    $msxml.resolveExternals = True
    $msxml.setProperty("SelectionLanguage", "XPath")
    $msxml.load('products.xml')
    If $msxml.parseError.errorCode = 0 Then
        $prods = $msxml.SelectNodes($xpath_tradename)
        If IsObj($prods) And $prods.Length > 0 Then
            ConsoleWrite("Number of products found: '" & $prods.Length & "'" & @CRLF)
            For $prod In $prods
                ConsoleWrite(@CRLF & "------ PRODUCT ------" & @CRLF)
                ConsoleWrite("Product name: '" & $prod.SelectSingleNode('name').text & "'" & @CRLF)
                ConsoleWrite("Product bay: '" & $prod.getAttribute('bay') & "'" & @CRLF)
            Next
            ConsoleWrite(@CRLF)
        Else
            ConsoleWrite("PRODUCT NOT FOUND" & @CRLF)
        EndIf
    Else
        MsgBox(17, 'Error', 'Error opening XML file: ' & @CRLF & @CRLF & $msxml.parseError.reason)
        SetError($msxml.parseError.errorCode)
    EndIf
EndIf

控制台输出

Search string: 'glycol'
XPath: '/products/product[tradenames/name[contains(.,'glycol')]]'
Number of products found: '2'

------ PRODUCT ------
Product name: 'DIPROPYLENE GLYCOL'
Product bay: '4'

------ PRODUCT ------
Product name: 'GLYCOL'
Product bay: '3'

答案 1 :(得分:1)

Autoit中最好的数据库解决方案是SQLite。

如果你想像专业人士那样做,你应该使用SQLite。

#include <SQLite.au3>
#include <SQLite.dll.au3>

Local $hQuery, $aRow
_SQLite_Startup()
ConsoleWrite("_SQLite_LibVersion=" & _SQLite_LibVersion() & @CRLF)
_SQLite_Open()
; Without $sCallback it's a resultless statement
_SQLite_Exec(-1, "Create table tblTest (a,b int,c single not null);" & _
        "Insert into tblTest values ('1',2,3);" & _
        "Insert into tblTest values (Null,5,6);")

Local $d = _SQLite_Exec(-1, "Select rowid,* From tblTest", "_cb") ; _cb will be called for each row

Func _cb($aRow)
    For $s In $aRow
        ConsoleWrite($s & @TAB)
    Next
    ConsoleWrite(@CRLF)
    ; Return $SQLITE_ABORT ; Would Abort the process and trigger an @error in _SQLite_Exec()
EndFunc   ;==>_cb
_SQLite_Close()
_SQLite_Shutdown()

; Output:
; 1     1   2   3
; 2         5   6

作为一个更简单的解决方案,我建议使用INI文件作为数据库。

[Voranol]
ProductName=Polyether Polyol
Flare=List I
Bay=1
ListPos=3

[Chem2]
ProductName=..
...

然后

   ; Read the INI section names. This will return a 1 dimensional array.
    Local $aArray = IniReadSectionNames($sFilePath)

    ; Check if an error occurred.
    If Not @error Then
        ; Enumerate through the array displaying the section names.
        For $i = 1 To $aArray[0]
            MsgBox($MB_SYSTEMMODAL, "", "Section: " & $aArray[$i])
        Next
    EndIf

现在INI文件大小(32kb)的窗口有限制。 这意味着,如果违反了该限制,某些Autoit INI功能将无效。

这可以通过使用您自己的INI函数来解决:

Func _IniReadSectionNamesEx($hFile)
    Local $iSize = FileGetSize($hFile) / 1024
    If $iSize <= 31 Then
        Local $aNameRead = IniReadSectionNames($hFile)
        If @error Then Return SetError(@error, 0, '')
        Return $aNameRead
    EndIf
    Local $aSectionNames = StringRegExp(@CRLF & FileRead($hFile) & @CRLF, '(?s)\n\s*\[(.*?)\]s*\r', 3)
    If IsArray($aSectionNames) = 0 Then Return SetError(1, 0, 0)
    Local $nUbound = UBound($aSectionNames)
    Local $aNameReturn[$nUbound + 1]
    $aNameReturn[0] = $nUbound
    For $iCC = 0 To $nUBound - 1
        $aNameReturn[$iCC + 1] = $aSectionNames[$iCC]
    Next
    Return $aNameReturn
EndFunc

Func _IniReadSectionEx($hFile, $vSection)
    Local $iSize = FileGetSize($hFile) / 1024
    If $iSize <= 31 Then
        Local $aSecRead = IniReadSection($hFile, $vSection)
        If @error Then Return SetError(@error, 0, '')
        Return $aSecRead
    EndIf
    Local $sFRead = @CRLF & FileRead($hFile) & @CRLF & '['
    $vSection = StringStripWS($vSection, 7)
    Local $aData = StringRegExp($sFRead, '(?s)(?i)\n\s*\[\s*' & $vSection & '\s*\]\s*\r\n(.*?)\[', 3)
    If IsArray($aData) = 0 Then Return SetError(1, 0, 0)
    Local $aKey = StringRegExp(@LF & $aData[0], '\n\s*(.*?)\s*=', 3)
    Local $aValue = StringRegExp(@LF & $aData[0], '\n\s*.*?\s*=(.*?)\r', 3)
    Local $nUbound = UBound($aKey)
    Local $aSection[$nUBound +1][2]
    $aSection[0][0] = $nUBound
    For $iCC = 0 To $nUBound - 1
        $aSection[$iCC + 1][0] = $aKey[$iCC]
        $aSection[$iCC + 1][1] = $aValue[$iCC]
    Next
    Return $aSection
EndFunc

答案 2 :(得分:1)

  

我需要查找商品名称,找到其正确的化学名称,然后获取该化学品的属性。

关系查询(SQLite

结构

SQLite data types。将记录插入productsubstance表可能为automated

enter image description here

product

定义商品名称。

id | name

1  | dowanol pmb
2  | dowanol pma
3  | dipropylene glycol
4  | dowanol pnp
5  | glycol blend
6  | isopar e
7  | isopar c
8  | isopar h
9  | Polyether Polyol
10 | Voranol

创建:

CREATE TABLE IF NOT EXISTS product (
   id   INTEGER PRIMARY KEY,
   name TEXT    UNIQUE
);
--CREATE INDEX IF NOT EXISTS index_product_name ON product(name);

插入记录:

INSERT INTO product (name) VALUES ('dowanol pmb');

substance

定义化学名称(和属性)。

id | name               | flare | bay

1  | Polyether Polyol   | 1     | 1
2  | DIPROPYLENE GLYCOL | 1     | 4
3  | GLYCOL             | 2     | 3
4  | PETROLEUM NAPHTA   | 0     | 5

创建:

CREATE TABLE IF NOT EXISTS substance (
   id    INTEGER PRIMARY KEY,
   name  TEXT    UNIQUE,
   flare INTEGER,
   bay   INTEGER
);
--CREATE INDEX IF NOT EXISTS index_substance_name ON substance(name);

插入记录:

INSERT INTO substance (name, flare, bay) VALUES ('Polyether Polyol', 1, 1);

relation

定义productsubstance表记录之间的关系(使用foreign keys)。

id | product | substance

1  | 1       | 2
2  | 2       | 2
3  | 3       | 2
4  | 4       | 2
5  | 5       | 3
6  | 6       | 4
7  | 7       | 4
8  | 8       | 4
9  | 9       | 4
10 | 10      | 1

创建:

CREATE TABLE IF NOT EXISTS relation (
   id        INTEGER PRIMARY KEY,
   product   INTEGER REFERENCES product(id),
   substance INTEGER REFERENCES substance(id),
   UNIQUE(  /* Constraint applies to *combination* of columns. */
      product,
      substance
   )
);
--CREATE INDEX IF NOT EXISTS index_relation_product   ON relation(product);
--CREATE INDEX IF NOT EXISTS index_relation_substance ON relation(substance);

插入记录:

INSERT INTO relation (
   product,
   substance
) VALUES (
   (SELECT id FROM product   WHERE name = 'dowanol pmb'),
   (SELECT id FROM substance WHERE name = 'DIPROPYLENE GLYCOL')
);

或者只是:

INSERT INTO relation (product, substance) VALUES (0, 1);

查看view_relation

Viewstored query),joiningcombinesproductsubstance表&#39;字段,根据relation表的记录(充当虚拟表,否定每次查询都需要包含基础JOIN运算符)。

name_product       | name_substance     | flare | bay

dowanol pmb        | DIPROPYLENE GLYCOL | 1     | 4
dowanol pma        | DIPROPYLENE GLYCOL | 1     | 4
dipropylene glycol | DIPROPYLENE GLYCOL | 1     | 4
dowanol pnp        | DIPROPYLENE GLYCOL | 1     | 4
glycol blend       | GLYCOL             | 2     | 3
isopar e           | PETROLEUM NAPTHA   | 0     | 5
isopar c           | PETROLEUM NAPTHA   | 0     | 5
isopar h           | PETROLEUM NAPTHA   | 0     | 5
Polyether Polyol   | PETROLEUM NAPTHA   | 0     | 5
Voranol            | Polyether Polyol   | 1     | 1

创建:

CREATE VIEW IF NOT EXISTS view_relation AS
   SELECT
      product.name    AS name_product,
      substance.name  AS name_substance,
      substance.flare,
      substance.bay
   FROM
      relation
   LEFT OUTER JOIN product   ON relation.product   = product.id
   LEFT OUTER JOIN substance ON relation.substance = substance.id
   ORDER BY
      product.id ASC
;

按商号

查询
name_product | name_substance   | flare | bay

Voranol      | Polyether Polyol | 1     | 1

查询:

SELECT
   *
FROM
   view_relation
WHERE
   name_product = 'Voranol'
;

或(没有观点):

SELECT
   product.name    AS name_product,
   substance.name  AS name_substance,
   substance.flare,
   substance.bay
FROM
   relation
WHERE
   product.name = 'Voranol'
LEFT OUTER JOIN product   ON relation.product   = product.id
LEFT OUTER JOIN substance ON relation.substance = substance.id
;

按实质查询

name_product       | name_substance     | flare | bay

dowanol pmb        | DIPROPYLENE GLYCOL | 1     | 4
dowanol pma        | DIPROPYLENE GLYCOL | 1     | 4
dipropylene glycol | DIPROPYLENE GLYCOL | 1     | 4
dowanol pnp        | DIPROPYLENE GLYCOL | 1     | 4

查询:

SELECT
   *
FROM
   view_relation
WHERE
   name_substance = 'DIPROPYLENE GLYCOL'
;

或(没有观点):

SELECT
   product.name    AS name_product,
   substance.name  AS name_substance,
   substance.flare,
   substance.bay
FROM
   relation
WHERE
   substance.name = 'DIPROPYLENE GLYCOL'
LEFT OUTER JOIN product   ON relation.product   = product.id
LEFT OUTER JOIN substance ON relation.substance = substance.id
;

的AutoIt

创建(并插入记录)单个表并查询它的示例:

#include <SQLite.au3>
#include <SQLite.dll.au3>
#include <Array.au3>

Global Const $g_iRecords   = 50
Global Const $g_sFileDb    = @ScriptDir & '\example.sqlite'
Global       $g_aCreate    = [ _
                             'CREATE TABLE IF NOT EXISTS example (id INTEGER PRIMARY KEY, name TEXT UNIQUE);' & @LF, _
                             '--CREATE INDEX IF NOT EXISTS index_example_name ON example(name);' & @LF _
                             ]
Global Const $g_sInsert    = 'INSERT INTO example (name) VALUES (%i);\n'
Global Const $g_sTransact1 = 'BEGIN TRANSACTION;' & @LF
Global Const $g_sTransact2 = 'END TRANSACTION;' & @LF
Global Const $g_sQuery     = 'SELECT * FROM example ORDER BY id ASC;'
Global Const $g_sMsgError  = 'sqlite.dll not found.' & @LF

Global       $g_hDb        = 0

Main()

Func Main()
    Local $sQuery     = ''
    Local $iResultCol = 0
    Local $iResultRow = 0
    Local $aResult

    For $i1 = 0 To UBound($g_aCreate, 1) -1
        $sQuery &= $g_aCreate[$i1]
    Next

    For $i1 = 1 To $g_iRecords
        $sQuery &= StringFormat($g_sInsert, _SQLite_FastEscape('example' & $i1))
    Next

    $sQuery = $g_sTransact1 & $sQuery & $g_sTransact2
    ConsoleWrite($sQuery)

    _SQLite_Startup()
    If @error Then
        ConsoleWrite($g_sMsgError)
        Exit
    EndIf

    _SQLite_Open($g_sFileDb)
    _SQLite_Exec($g_hDb, $sQuery)
    _SQLite_GetTable2d($g_hDb, $g_sQuery, $aResult, $iResultRow, $iResultCol)
    _SQLite_Close($g_hDb)
    _SQLite_Shutdown()

    _ArrayDisplay($aResult)
    Exit
EndFunc
相关问题