Base de Dados

É necessária uma validação que permita analisar, no mesmo documento, as chaves de várias tabelas e obrigue a unicidade de determinado campo apenas na tabela em que aquele é chave. Pode acontecer várias tabelas terem valores iguais, mas estes corresponderem ao campo chave apenas numa tabela. Em XML, poderia usar-se o atributo id em cada elemento de cada campo chave, mas tal atributo tem que ser único em todo o documento e não em cada tabela como pretendido. Como este mecanismo não resolve o problema, será necessário recorrer a uma restrição.

Neste exemplo não se apresenta um caso genérico, mas antes o caso de uma base de dados particular, com um número de tabelas específico e cada tabela com um conjunto de campos perfeitamente conhecido.

Ficheiro com o DTD:

<!-- Base de dados particular -->
<!ELEMENT DB (STRUCTURE, DATA)>
<!ELEMENT STRUCTURE (TPROD, TORDERS)>
<!ELEMENT TPROD (COLUMNS1, KEYS)>
<!ATTLIST TPROD
	NAME (prod) #REQUIRED
>
<!ELEMENT COLUMNS1 (COLUMN1+)>
<!ELEMENT COLUMN1 EMPTY>
<!ATTLIST COLUMN1
	NAME (code | description) #REQUIRED
	TYPE CDATA #REQUIRED
	SIZE (10 | 50) #REQUIRED
	NULL (yes | no) #REQUIRED
>
<!ELEMENT TORDERS (COLUMNS2, KEYS)>
<!ATTLIST TORDERS
	NAME (orders) #REQUIRED
>
<!ELEMENT COLUMNS2 (COLUMN2+)>
<!ELEMENT COLUMN2 EMPTY>
<!ATTLIST COLUMN2
	NAME (orderc | code | quant) #REQUIRED
	TYPE CDATA #REQUIRED
	SIZE (10 | 50) #REQUIRED
	NULL (yes | no) #REQUIRED
>
<!ELEMENT KEYS (PKEYS)>
<!ELEMENT PKEYS (PKEY)+>
<!ATTLIST PKEYS
	TYPE (simple | complex) #REQUIRED
>
<!ELEMENT PKEY EMPTY>
<!ATTLIST PKEY
	NAME CDATA #REQUIRED
>
<!ELEMENT DATA (iPROD, iORDERS)>
<!ELEMENT iPROD (items-REG1+)>
<!ATTLIST iPROD
	NAME (prod) #REQUIRED
>
<!ELEMENT items-REG1 (code, description)>
<!ELEMENT code (#PCDATA)>
<!ELEMENT description (#PCDATA)>
<!ELEMENT iORDERS (items-REG2+)>
<!ATTLIST iORDERS
	NAME (orders) #REQUIRED
>
<!ELEMENT items-REG2 (orderc, code, quant)>
<!ELEMENT orderc (#PCDATA)>
<!ELEMENT quant (#PCDATA)>

Ficheiro com as restrições:

dbml\res\dbml_e-cc01.xml
<CONSTRAINT>

<SELECTOR SELEXP="//iPROD/items-REG1"/>

<LET NAME="keyprod" VALUE="code"/>

<CC> count(//iPROD/items-REG1[code = $keyprod]) = 1

</CC>

<ACTION>

<MESSAGE>WARNING: code: <VALUE SELEXP="code"/> is not unique!

</MESSAGE>

</ACTION>

</CONSTRAINT>
<CONSTRAINT>

<SELECTOR SELEXP="//iORDERS/items-REG2"/>

<LET NAME="keyorderc" VALUE="orderc"/>

<CC> count(//iORDERS/items-REG2[orderc = $keyorderc]) = 1

</CC>

<ACTION>

<MESSAGE>WARNING: orderc: <VALUE SELEXP="orderc"/> is not unique!

</MESSAGE>

</ACTION>

</CONSTRAINT>

Ficheiro com a stylesheet:

dbml\xsl\dbml_e-cc01.xsl
<xsl:stylesheet>
<xsl:output></xsl:output>
<xsl:template>
<doc-status>
<xsl:apply-templates></xsl:apply-templates>
<xsl:apply-templates></xsl:apply-templates>
</doc-status>
</xsl:template>
<xsl:template>
<xsl:variable>
<xsl:value-of></xsl:value-of>
</xsl:variable>
<xsl:if>
<err-message>
      WARNING: 
        code: 
<xsl:value-of></xsl:value-of>
is not unique! </err-message>
</xsl:if>
<xsl:apply-templates></xsl:apply-templates>
</xsl:template>
<xsl:template></xsl:template>
<xsl:template>
<xsl:variable>
<xsl:value-of></xsl:value-of>
</xsl:variable>
<xsl:if>
<err-message>
      WARNING: 
        orderc: 
<xsl:value-of></xsl:value-of>
is not unique! </err-message>
</xsl:if>
<xsl:apply-templates></xsl:apply-templates>
</xsl:template>
<xsl:template></xsl:template>
<xsl:template></xsl:template>
</xsl:stylesheet>


Constraint:

Para o caso da primeira tabela, será necessária uma restrição que analise o número de ocorrências da chave code e retorne um erro no caso de múltiplas ocorrências.

Usa-se o elemento LET, para colocar em keyprod a lista de valores que o elemento code toma no contexto //iPROD/items-REG1. Depois conta-se o número de ocorrências de cada instância de code na lista keyprod. No exemplo apresentado, a validação resultaria verdadeira uma vez que o valor de cada elemento code na sub-árvore iPROD é único. Repare-se que existem elementos code com um valor repetido, mas esses estão na sub-árvore iORDERS, não sendo por isso considerados, como pretendido.

Restrições: dbml\res\dbml_e_res1.txt
<CONSTRAINT>

<SELECTOR SELEXP="//iPROD/items-REG1"/>

<LET NAME="keyprod" VALUE="code"/>

<CC> count(//iPROD/items-REG1[code = $keyprod]) = 1

</CC>

<ACTION>

<MESSAGE>WARNING: code: <VALUE SELEXP="code"/> is not unique!

</MESSAGE>

</ACTION>

</CONSTRAINT>

Para o caso da segunda tabela, será necessária uma restrição que analise o número de ocorrências da chave orderc retorne um erro no caso de múltiplas ocorrências.

Desta feita o elemento LET serve para colocar em keyorderc a lista de valores que o elemento orderc toma no contexto //iORDERS/items-REG2. Depois conta-se o número de ocorrências de cada instância de orderc na lista keyorderc. No exemplo apresentado, a validação resultaria verdadeira uma vez que o valor de cada elemento orderc é único.

Restrições: dbml\res\dbml_e_res2.txt
<CONSTRAINT>

<SELECTOR SELEXP="//iORDERS/items-REG2"/>

<LET NAME="keyorderc" VALUE="orderc"/>

<CC> count(//iORDERS/items-REG2[orderc = $keyorderc]) = 1

</CC>

<ACTION>

<MESSAGE>WARNING: orderc: <VALUE SELEXP="orderc"/> is not unique!

</MESSAGE>

</ACTION>

</CONSTRAINT>


Aplicações:


Aplicação:

dbml01

Documento em que, o valor de cada elemento code é único na sub-árvore iPROD e, simultaneamente, o valor de cada elemento orderc é único na sub-árvore iORDERS. Obteve-se um documento sem quaisquer erros.

dbml\xml\dbml_e02.xml

<DB>
<STRUCTURE>
<TPROD>
<COLUMNS1>
<COLUMN1></COLUMN1>
<COLUMN1></COLUMN1>
</COLUMNS1>
<KEYS>
<PKEYS>
<PKEY></PKEY>
</PKEYS>
</KEYS>
</TPROD>
<TORDERS>
<COLUMNS2>
<COLUMN2></COLUMN2>
<COLUMN2></COLUMN2>
<COLUMN2></COLUMN2>
</COLUMNS2>
<KEYS>
<PKEYS>
<PKEY></PKEY>
</PKEYS>
</KEYS>
</TORDERS>
</STRUCTURE>
<DATA>
<iPROD>
<items-REG1>
<code>a111</code>
<description>leite agros meio-gordo</description>
</items-REG1>
<items-REG1>
<code>a115</code>
<description>leite agros chocolatado</description>
</items-REG1>
<items-REG1>
<code>a112</code>
<description>leite agros meio-gordo</description>
</items-REG1>
<items-REG1>
<code>a113</code>
<description>leite mimosa chocolatado</description>
</items-REG1>
<items-REG1>
<code>a114</code>
<description>leite mimosa meio-gordo</description>
</items-REG1>
<items-REG1>
<code>a116</code>
<description>leite ucal chocolatado</description>
</items-REG1>
</iPROD>
<iORDERS>
<items-REG2>
<orderc>o012001</orderc>
<code>a111</code>
<quant>10</quant>
</items-REG2>
<items-REG2>
<orderc>o072001</orderc>
<code>a115</code>
<quant>20</quant>
</items-REG2>
<items-REG2>
<orderc>o142001</orderc>
<code>a111</code>
<quant>15</quant>
</items-REG2>
<items-REG2>
<orderc>o172001</orderc>
<code>a114</code>
<quant>4</quant>
</items-REG2>
</iORDERS>
</DATA>
</DB>

dbml\out\dbml_e02e.xml

<doc-status></doc-status>

Aplicação:

dbml02

Documento em que pelo menos dois elementos code na sub-árvore iPROD têm o mesmo valor, mas o valor de cada elemento orderc é único na sub-árvore iORDERS. Obteve-se um documento que descreve o erro encontrado, por exemplo para o caso em que a primeira tabela (TPROD) tem 6 elementos code, em que um é único, um ocorre duas vezes e o outro ocorre três vezes.

dbml\xml\dbml_e01.xml

<DB>
<STRUCTURE>
<TPROD>
<COLUMNS1>
<COLUMN1></COLUMN1>
<COLUMN1></COLUMN1>
</COLUMNS1>
<KEYS>
<PKEYS>
<PKEY></PKEY>
</PKEYS>
</KEYS>
</TPROD>
<TORDERS>
<COLUMNS2>
<COLUMN2></COLUMN2>
<COLUMN2></COLUMN2>
<COLUMN2></COLUMN2>
</COLUMNS2>
<KEYS>
<PKEYS>
<PKEY></PKEY>
</PKEYS>
</KEYS>
</TORDERS>
</STRUCTURE>
<DATA>
<iPROD>
<items-REG1>
<code>a111</code>
<description>leite agros meio-gordo</description>
</items-REG1>
<items-REG1>
<code>a115</code>
<description>leite agros chocolatado</description>
</items-REG1>
<items-REG1>
<code>a112</code>
<description>leite agros meio-gordo</description>
</items-REG1>
<items-REG1>
<code>a115</code>
<description>leite agros chocolatado</description>
</items-REG1>
<items-REG1>
<code>a112</code>
<description>leite agros meio-gordo</description>
</items-REG1>
<items-REG1>
<code>a115</code>
<description>leite agros chocolatado</description>
</items-REG1>
</iPROD>
<iORDERS>
<items-REG2>
<orderc>o012001</orderc>
<code>a111</code>
<quant>10</quant>
</items-REG2>
<items-REG2>
<orderc>o072001</orderc>
<code>a115</code>
<quant>20</quant>
</items-REG2>
<items-REG2>
<orderc>o142001</orderc>
<code>a111</code>
<quant>15</quant>
</items-REG2>
<items-REG2>
<orderc>o172001</orderc>
<code>a114</code>
<quant>4</quant>
</items-REG2>
</iORDERS>
</DATA>
</DB>

dbml\out\dbml_e01e.xml

<doc-status>
<err-message>
      WARNING: 
        code: a115 is not unique!
    </err-message>
<err-message>
      WARNING: 
        code: a112 is not unique!
    </err-message>
<err-message>
      WARNING: 
        code: a115 is not unique!
    </err-message>
<err-message>
      WARNING: 
        code: a112 is not unique!
    </err-message>
<err-message>
      WARNING: 
        code: a115 is not unique!
    </err-message>
</doc-status>

Aplicação:

dbml03

Documento em que o valor de cada elemento code é único na sub-árvore iPROD, mas pelo menos dois elementos orderc na sub-árvore iORDERS têm o mesmo valor. Obteve-se um documento que descreve o erro encontrado.

dbml\xml\dbml_e03.xml

<DB>
<STRUCTURE>
<TPROD>
<COLUMNS1>
<COLUMN1></COLUMN1>
<COLUMN1></COLUMN1>
</COLUMNS1>
<KEYS>
<PKEYS>
<PKEY></PKEY>
</PKEYS>
</KEYS>
</TPROD>
<TORDERS>
<COLUMNS2>
<COLUMN2></COLUMN2>
<COLUMN2></COLUMN2>
<COLUMN2></COLUMN2>
</COLUMNS2>
<KEYS>
<PKEYS>
<PKEY></PKEY>
</PKEYS>
</KEYS>
</TORDERS>
</STRUCTURE>
<DATA>
<iPROD>
<items-REG1>
<code>a111</code>
<description>leite agros meio-gordo</description>
</items-REG1>
<items-REG1>
<code>a115</code>
<description>leite agros chocolatado</description>
</items-REG1>
<items-REG1>
<code>a112</code>
<description>leite agros meio-gordo</description>
</items-REG1>
<items-REG1>
<code>a113</code>
<description>leite mimosa chocolatado</description>
</items-REG1>
<items-REG1>
<code>a114</code>
<description>leite mimosa meio-gordo</description>
</items-REG1>
<items-REG1>
<code>a116</code>
<description>leite ucal chocolatado</description>
</items-REG1>
</iPROD>
<iORDERS>
<items-REG2>
<orderc>o012001</orderc>
<code>a111</code>
<quant>10</quant>
</items-REG2>
<items-REG2>
<orderc>o072001</orderc>
<code>a115</code>
<quant>20</quant>
</items-REG2>
<items-REG2>
<orderc>o142001</orderc>
<code>a111</code>
<quant>15</quant>
</items-REG2>
<items-REG2>
<orderc>o172001</orderc>
<code>a114</code>
<quant>4</quant>
</items-REG2>
<items-REG2>
<orderc>o072001</orderc>
<code>a115</code>
<quant>20</quant>
</items-REG2>
<items-REG2>
<orderc>o172001</orderc>
<code>a111</code>
<quant>30</quant>
</items-REG2>
</iORDERS>
</DATA>
</DB>

dbml\out\dbml_e03e.xml

<doc-status>
<err-message>
      WARNING: 
        orderc: o072001 is not unique!
    </err-message>
<err-message>
      WARNING: 
        orderc: o172001 is not unique!
    </err-message>
<err-message>
      WARNING: 
        orderc: o072001 is not unique!
    </err-message>
<err-message>
      WARNING: 
        orderc: o172001 is not unique!
    </err-message>
</doc-status>

Aplicação:

dbml04

Documento em que pelo menos dois elementos code na sub-árvore iPROD têm o mesmo valor e, simultaneamente, pelo menos dois elementos orderc na sub-árvore iORDERS têm o mesmo valor. Obteve-se um documento que descreve o erro encontrado, por exemplo para o caso em que a primeira tabela (TPROD) tem 6 elementos code, em que um é único, um ocorre duas vezes e o outro ocorre três vezes e a segunda tabela (TORDERS) tem 6 elementos orderc, em que dois são únicos e os outros dois ocorrem duas vezes cada um.

dbml\xml\dbml_e04.xml

<DB>
<STRUCTURE>
<TPROD>
<COLUMNS1>
<COLUMN1></COLUMN1>
<COLUMN1></COLUMN1>
</COLUMNS1>
<KEYS>
<PKEYS>
<PKEY></PKEY>
</PKEYS>
</KEYS>
</TPROD>
<TORDERS>
<COLUMNS2>
<COLUMN2></COLUMN2>
<COLUMN2></COLUMN2>
<COLUMN2></COLUMN2>
</COLUMNS2>
<KEYS>
<PKEYS>
<PKEY></PKEY>
</PKEYS>
</KEYS>
</TORDERS>
</STRUCTURE>
<DATA>
<iPROD>
<items-REG1>
<code>a111</code>
<description>leite agros meio-gordo</description>
</items-REG1>
<items-REG1>
<code>a115</code>
<description>leite agros chocolatado</description>
</items-REG1>
<items-REG1>
<code>a112</code>
<description>leite agros meio-gordo</description>
</items-REG1>
<items-REG1>
<code>a115</code>
<description>leite agros chocolatado</description>
</items-REG1>
<items-REG1>
<code>a112</code>
<description>leite agros meio-gordo</description>
</items-REG1>
<items-REG1>
<code>a115</code>
<description>leite agros chocolatado</description>
</items-REG1>
</iPROD>
<iORDERS>
<items-REG2>
<orderc>o012001</orderc>
<code>a111</code>
<quant>10</quant>
</items-REG2>
<items-REG2>
<orderc>o072001</orderc>
<code>a115</code>
<quant>20</quant>
</items-REG2>
<items-REG2>
<orderc>o142001</orderc>
<code>a111</code>
<quant>15</quant>
</items-REG2>
<items-REG2>
<orderc>o172001</orderc>
<code>a114</code>
<quant>4</quant>
</items-REG2>
<items-REG2>
<orderc>o072001</orderc>
<code>a115</code>
<quant>20</quant>
</items-REG2>
<items-REG2>
<orderc>o172001</orderc>
<code>a111</code>
<quant>30</quant>
</items-REG2>
</iORDERS>
</DATA>
</DB>

dbml\out\dbml_e04e.xml

<doc-status>
<err-message>
      WARNING: 
        code: a115 is not unique!
    </err-message>
<err-message>
      WARNING: 
        code: a112 is not unique!
    </err-message>
<err-message>
      WARNING: 
        code: a115 is not unique!
    </err-message>
<err-message>
      WARNING: 
        code: a112 is not unique!
    </err-message>
<err-message>
      WARNING: 
        code: a115 is not unique!
    </err-message>
<err-message>
      WARNING: 
        orderc: o072001 is not unique!
    </err-message>
<err-message>
      WARNING: 
        orderc: o172001 is not unique!
    </err-message>
<err-message>
      WARNING: 
        orderc: o072001 is not unique!
    </err-message>
<err-message>
      WARNING: 
        orderc: o172001 is not unique!
    </err-message>
</doc-status>
Back