What parameters can I change in graphviz to make a graph look better? - dot

I'm using graphviz to create a diagram showing a database schema which is based on pony. However, the schema ends up being extremely complicated .
What parameters can I modify in my code to make this better looking?
Right now I'm using "neato" as the engine (which gave better results vs the default) but don't know which other parameters I could modify.
Script to define schema using ponyorm:
from pony import orm
from pony.orm import Required, Optional, Set, db_session, show, composite_key
from decimal import Decimal
import datetime as dtt
import pandas as pd
###############################################################################
# DATABASE DEFINITION
###############################################################################
_db = orm.Database()
class Helper:
def __repr__(self):
class_name = type(self).__name__
return '<' + class_name + self.label() + '>'
class Table1(Helper, _db.Entity):
attr0 = Required(str, unique=True)
table2s = Set('Table2')
class Table2(Helper, _db.Entity):
name = Required(str, unique=True)
table1 = Required('Table1')
table6s = Set('Table6')
notes = Optional(str)
class Table3(Helper, _db.Entity):
name = Required(str, unique=True)
table6s = Set('Table6')
class Table4(Helper, _db.Entity):
number = Required(str, unique=True)
valid_from = Required(dtt.datetime)
valid_to = Optional(dtt.datetime)
table6s = Required('Table6')
class Table5(Helper, _db.Entity):
text = Required(str, unique=True)
table6s = Required('Table6')
class Table6(Helper, _db.Entity):
table2 = Required('Table2')
table3 = Required('Table3')
description = Required(str, unique=True)
table6 = Optional('Table5')
date_opened = Optional(dtt.datetime)
date_closed = Optional(dtt.datetime)
table4s = Set('Table4')
table7s = Set('Table7')
table8 = Required('Table8')
table10 = Optional('Table10')
class Table7(Helper, _db.Entity):
date = Required(dtt.datetime)
start = Required(dtt.datetime)
description = Required(str)
amount = Required(Decimal)
table10 = Required('Table10')
table6 = Required('Table6')
tabel14s = Set('Table14')
table9s = Set('Table9')
class Table8(Helper, _db.Entity):
name = Required(str)
is_true = Required(bool)
is_false = Required(bool)
table11s = Set('Table11')
table6s = Set('Table6')
class Table9(Helper, _db.Entity):
date = Required(dtt.datetime)
description = Required(str)
table12s = Set('Table12')
table11s = Set('Table11')
table7s = Set('Table7')
table9s = Set('Table9', reverse='table9s')
class Table10(Helper, _db.Entity):
name = Required(str, unique=True)
transactions = Set('Table11')
table7s = Set('Table7')
table6s = Set('Table6')
class Table11(Helper, _db.Entity):
amount = Required(Decimal)
table10 = Required('Table10')
table8= Required('Table8')
table9s= Set('Table9')
class Table12(Helper, _db.Entity):
name = Required(str, unique=True)
table9s = Set('Table9')
class Table13(Helper, _db.Entity):
name = Required(str, unique=True)
table14s = Set('Table14')
class Table14(Helper, _db.Entity):
filename = Required(str, unique=True)
suffix = Required(str)
table13 = Required('Table13')
date_added = Required(dtt.datetime)
period_start = Optional(dtt.datetime)
period_end = Optional(dtt.datetime)
description = Optional(str)
table7s = Set('Table7')
###############################################################################
# CONNECT TO DATABASE
###############################################################################
orm.set_sql_debug(False)
_db.bind(provider='sqlite', filename=':memory:', create_db=True)
_db.generate_mapping(create_tables=True)
commit = _db.commit
select = orm.select
entities = _db.entities
# hack to overcome pyflakes thinking that variables aren't used
show = show
db_session = db_session
Python functions to load ponyorm database and create dot file
def get_port(s):
return 'port="' + s.replace(' ', '_') + '"'
def calculate_graph():
s = gv.Graph('graph', node_attr={'shape': 'plaintext'}, engine='neato',
graph_attr={'splines': 'true', 'overlap': 'false'})
edges = []
for entity in db.entities:
table_def = '<table border="0" cellborder="1" cellspacing="0">'
header = (f'<tr><td bgcolor="black"><font color="white">{entity}'
'</font></td></tr>')
attrs = ''
for attr in db.entities[entity]._attrs_:
name = attr.name
port = get_port(name)
attrs += f'<tr><td {port}>{name}</td></tr>'
# if isinstance(attr, db.Set):
if attr.py_type in db.entities.values():
edges.append((f'{entity}:{attr.name}',
f'{attr.py_type.__name__}:id'))
s_struct = '<' + table_def + header + attrs + '</table>>'
s.node(entity, s_struct)
s.edges(edges)
s.attr(overlap='false')
s.view()
dot file code (automatically generated):
graph "graph" {
graph [overlap=false splines=true]
node [shape=plaintext]
Table1 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table1</font></td></tr><tr><td port="id">id</td></tr><tr><td port="attr0">attr0</td></tr><tr><td port="table2s">table2s</td></tr></table>>]
Table2 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table2</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table1">table1</td></tr><tr><td port="table6s">table6s</td></tr><tr><td port="notes">notes</td></tr></table>>]
Table3 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table3</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
Table4 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table4</font></td></tr><tr><td port="id">id</td></tr><tr><td port="number">number</td></tr><tr><td port="valid_from">valid_from</td></tr><tr><td port="valid_to">valid_to</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
Table5 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table5</font></td></tr><tr><td port="id">id</td></tr><tr><td port="text">text</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
Table6 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table6</font></td></tr><tr><td port="id">id</td></tr><tr><td port="table2">table2</td></tr><tr><td port="table3">table3</td></tr><tr><td port="description">description</td></tr><tr><td port="table6">table6</td></tr><tr><td port="date_opened">date_opened</td></tr><tr><td port="date_closed">date_closed</td></tr><tr><td port="table4s">table4s</td></tr><tr><td port="table7s">table7s</td></tr><tr><td port="table8">table8</td></tr><tr><td port="table10">table10</td></tr></table>>]
Table7 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table7</font></td></tr><tr><td port="id">id</td></tr><tr><td port="date">date</td></tr><tr><td port="start">start</td></tr><tr><td port="description">description</td></tr><tr><td port="amount">amount</td></tr><tr><td port="table10">table10</td></tr><tr><td port="table6">table6</td></tr><tr><td port="tabel14s">tabel14s</td></tr><tr><td port="table9s">table9s</td></tr></table>>]
Table8 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table8</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="is_true">is_true</td></tr><tr><td port="is_false">is_false</td></tr><tr><td port="table11s">table11s</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
Table9 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table9</font></td></tr><tr><td port="id">id</td></tr><tr><td port="date">date</td></tr><tr><td port="description">description</td></tr><tr><td port="table12s">table12s</td></tr><tr><td port="table11s">table11s</td></tr><tr><td port="table7s">table7s</td></tr><tr><td port="table9s">table9s</td></tr></table>>]
Table10 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table10</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="transactions">transactions</td></tr><tr><td port="table7s">table7s</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
Table11 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table11</font></td></tr><tr><td port="id">id</td></tr><tr><td port="amount">amount</td></tr><tr><td port="table10">table10</td></tr><tr><td port="table8">table8</td></tr><tr><td port="table9s">table9s</td></tr></table>>]
Table12 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table12</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table9s">table9s</td></tr></table>>]
Table13 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table13</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table14s">table14s</td></tr></table>>]
Table14 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table14</font></td></tr><tr><td port="id">id</td></tr><tr><td port="filename">filename</td></tr><tr><td port="suffix">suffix</td></tr><tr><td port="table13">table13</td></tr><tr><td port="date_added">date_added</td></tr><tr><td port="period_start">period_start</td></tr><tr><td port="period_end">period_end</td></tr><tr><td port="description">description</td></tr><tr><td port="table7s">table7s</td></tr></table>>]
Table1:table2s -- Table2:id
Table2:table1 -- Table1:id
Table2:table6s -- Table6:id
Table3:table6s -- Table6:id
Table4:table6s -- Table6:id
Table5:table6s -- Table6:id
Table6:table2 -- Table2:id
Table6:table3 -- Table3:id
Table6:table6 -- Table5:id
Table6:table4s -- Table4:id
Table6:table7s -- Table7:id
Table6:table8 -- Table8:id
Table6:table10 -- Table10:id
Table7:table10 -- Table10:id
Table7:table6 -- Table6:id
Table7:tabel14s -- Table14:id
Table7:table9s -- Table9:id
Table8:table11s -- Table11:id
Table8:table6s -- Table6:id
Table9:table12s -- Table12:id
Table9:table11s -- Table11:id
Table9:table7s -- Table7:id
Table9:table9s -- Table9:id
Table10:transactions -- Table11:id
Table10:table7s -- Table7:id
Table10:table6s -- Table6:id
Table11:table10 -- Table10:id
Table11:table8 -- Table8:id
Table11:table9s -- Table9:id
Table12:table9s -- Table9:id
Table13:table14s -- Table14:id
Table14:table13 -- Table13:id
Table14:table7s -- Table7:id
overlap=false
}

Using ortho routing will make the diagram a bit more appetising.
Edges will run over other things inevitably sooner or later, so setting a little transparency might help a little as well (edge[color="#00000080"]).
Also, since it's about relations between tables, you might want to make the graph a digraph, so you can see in which direction they're going (or alternatively use dir and arrowtail/ arrowhead attributes on the global edge declaration i.e. edge[color="#00000080" dir=both arrowtail=crow arrowhead=none]) The sample below simply makes it a digraph
Getting diagrams to look nice can take a lot of tinkering. The ortho routing is the closest I've found to a 'magic' attribute. Drawback is that it doesn't scale to big graphs (several hundreds of nodes or more).
digraph "graph" {
graph [overlap=true splines=ortho]
edge[color="#00000080"]
node [shape=plaintext]
Table1 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table1</font></td></tr><tr><td port="id">id</td></tr><tr><td port="attr0">attr0</td></tr><tr><td port="table2s">table2s</td></tr></table>>]
Table2 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table2</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table1">table1</td></tr><tr><td port="table6s">table6s</td></tr><tr><td port="notes">notes</td></tr></table>>]
Table3 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table3</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
Table4 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table4</font></td></tr><tr><td port="id">id</td></tr><tr><td port="number">number</td></tr><tr><td port="valid_from">valid_from</td></tr><tr><td port="valid_to">valid_to</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
Table5 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table5</font></td></tr><tr><td port="id">id</td></tr><tr><td port="text">text</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
Table6 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table6</font></td></tr><tr><td port="id">id</td></tr><tr><td port="table2">table2</td></tr><tr><td port="table3">table3</td></tr><tr><td port="description">description</td></tr><tr><td port="table6">table6</td></tr><tr><td port="date_opened">date_opened</td></tr><tr><td port="date_closed">date_closed</td></tr><tr><td port="table4s">table4s</td></tr><tr><td port="table7s">table7s</td></tr><tr><td port="table8">table8</td></tr><tr><td port="table10">table10</td></tr></table>>]
Table7 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table7</font></td></tr><tr><td port="id">id</td></tr><tr><td port="date">date</td></tr><tr><td port="start">start</td></tr><tr><td port="description">description</td></tr><tr><td port="amount">amount</td></tr><tr><td port="table10">table10</td></tr><tr><td port="table6">table6</td></tr><tr><td port="tabel14s">tabel14s</td></tr><tr><td port="table9s">table9s</td></tr></table>>]
Table8 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table8</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="is_true">is_true</td></tr><tr><td port="is_false">is_false</td></tr><tr><td port="table11s">table11s</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
Table9 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table9</font></td></tr><tr><td port="id">id</td></tr><tr><td port="date">date</td></tr><tr><td port="description">description</td></tr><tr><td port="table12s">table12s</td></tr><tr><td port="table11s">table11s</td></tr><tr><td port="table7s">table7s</td></tr><tr><td port="table9s">table9s</td></tr></table>>]
Table10 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table10</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="transactions">transactions</td></tr><tr><td port="table7s">table7s</td></tr><tr><td port="table6s">table6s</td></tr></table>>]
Table11 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table11</font></td></tr><tr><td port="id">id</td></tr><tr><td port="amount">amount</td></tr><tr><td port="table10">table10</td></tr><tr><td port="table8">table8</td></tr><tr><td port="table9s">table9s</td></tr></table>>]
Table12 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table12</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table9s">table9s</td></tr></table>>]
Table13 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table13</font></td></tr><tr><td port="id">id</td></tr><tr><td port="name">name</td></tr><tr><td port="table14s">table14s</td></tr></table>>]
Table14 [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="black"><font color="white">Table14</font></td></tr><tr><td port="id">id</td></tr><tr><td port="filename">filename</td></tr><tr><td port="suffix">suffix</td></tr><tr><td port="table13">table13</td></tr><tr><td port="date_added">date_added</td></tr><tr><td port="period_start">period_start</td></tr><tr><td port="period_end">period_end</td></tr><tr><td port="description">description</td></tr><tr><td port="table7s">table7s</td></tr></table>>]
Table1:table2s -> Table2:id
Table2:table1 -> Table1:id
Table2:table6s -> Table6:id
Table3:table6s -> Table6:id
Table4:table6s -> Table6:id
Table5:table6s -> Table6:id
Table6:table2 -> Table2:id
Table6:table3 -> Table3:id
Table6:table6 -> Table5:id
Table6:table4s -> Table4:id
Table6:table7s -> Table7:id
Table6:table8 -> Table8:id
Table6:table10 -> Table10:id
Table7:table10 -> Table10:id
Table7:table6 -> Table6:id
Table7:tabel14s -> Table14:id
Table7:table9s -> Table9:id
Table8:table11s -> Table11:id
Table8:table6s -> Table6:id
Table9:table12s -> Table12:id
Table9:table11s -> Table11:id
Table9:table7s -> Table7:id
Table9:table9s -> Table9:id
Table10:transactions -> Table11:id
Table10:table7s -> Table7:id
Table10:table6s -> Table6:id
Table11:table10 -> Table10:id
Table11:table8 -> Table8:id
Table11:table9s -> Table9:id
Table12:table9s -> Table9:id
Table13:table14s -> Table14:id
Table14:table13 -> Table13:id
Table14:table7s -> Table7:id
overlap=false
}
B.t.w. you landed on using the neato algorithm (which in this case indeed gives the best result) - for the default algorithm (dot) playing around with the rankdir attribute on the graph might help out (in your case setting it to LR)

Related

Why does this SQLite UPDATE statement write changes to all records in the table?

This query returns 40319 records:
SELECT artist,
title,
composer AS alib_composer,
master.composer AS master_composer
FROM alib
INNER JOIN
master ON hex(alib.__path) = hex(master.__path) AND
alib.l_title = lower(master.title) AND
alib.composer != master.composer AND
length(alib.composer) != length(master.composer) AND
master.composer LIKE "% %" AND
alib.composer NOT LIKE "% %";
Translating above into the following UPDATE query results in all records in alib being updated. Could someone help me understand why this is the case?
UPDATE alib
SET composer = (
SELECT composer
FROM master
WHERE hex(alib.__path) = hex(master.__path) AND
alib.l_title = lower(master.title) AND
alib.composer != master.composer AND
length(alib.composer) != length(master.composer) AND
master.composer LIKE "% %" AND
alib.composer NOT LIKE "% %"
);
I suspect I know why, but turning the update into something like this:
UPDATE alib
SET composer = master.composer
WHERE hex(alib.__path) = hex(master.__path) AND
alib.l_title = lower(master.title) AND
alib.composer != master.composer AND
length(alib.composer) != length(master.composer) AND
master.composer LIKE "% %" AND
alib.composer NOT LIKE "% %";
causes SQLite to complain:
Error while executing SQL query on database 'x': no such column: master.composer
Because there is no WHERE clause on the outer/main UPDATE SQL i.e. it is basiclly
UPDATE alib SET composer = the_result_of_the_subquery;
i.e. UPDATE every row.
You want a WHERE clause to say which rows to update along the lines of :-
UPDATE alib SET composer = the_result_of_the_subquery WHERE ??????;
Or to use your code :-
UPDATE alib
SET composer = (
SELECT composer
FROM master
WHERE hex(alib.__path) = hex(master.__path) AND
alib.l_title = lower(master.title) AND
alib.composer != master.composer AND
length(alib.composer) != length(master.composer) AND
master.composer LIKE "% %" AND
alib.composer NOT LIKE "% %"
)
WHERE the_expression_to_restrict_which_rows_are_updated
;
This hasn't been fully tested but this may be solution you are looking for :-
WITH cte AS
(
SELECT
master.composer AS master_composer,
alib.rowid AS arowid
FROM alib
INNER JOIN
master ON hex(alib.__path) = hex(master.__path)
AND alib.l_title = lower(master.title)
AND alib.composer != master.composer
AND length(alib.composer) != length(master.composer)
AND master.composer LIKE '% %'
AND alib.composer NOT LIKE '% %'
)
UPDATE alib
SET composer =
(
SELECT cte.master_composer FROM cte WHERE cte.arowid = alib.rowid
)
WHERE alib.rowid IN (SELECT arowid FROM cte);
this uses a Common Table Expresssion(CTE) (temporay table that exists just for the query).
It utlises the rowid (a hidden column that every table has other than WITHOUT ROWID tables).
That is the CTE is based upon your original query that extracts the rows from alib that need to be updated. It only needs the composer from the master table and the rowid of the alib table for the update.
The UPDATE sets the composer to the value of the master_composer column of the respective row from the CTE according to the rowid of the row being updated.
The UPDATEs are only applied to rows that have a matching row in the CTE.
Testing (limited)
The following SQL was used for testing :-
DROP TABLE IF EXISTS alib;
DROP TABLE IF EXISTS master;
CREATE TABLE IF NOT EXISTS alib (__path,l_title,composer);
CREATE TABLE IF NOT EXISTS master (__path,title,artist,composer);
INSERT INTO alib VALUES
('path1','this','bert'),
('path2','something else','Joe'),
('path2','something else','Joe'), -- duplicate likely irrelevant but still updated
('path2','something else','Joe Someone'), -- already has space in composer skipped
('path100','an so on','x') -- no equivalent in master
;
INSERT INTO master VALUES
('path1','this','fred','bert'), -- ignored as no space
('path1','this','fred bloggs','Julia smith'),
('path2','something else','Alison','Joe Brown')
;
/* DEMO OF EXTRACTED ROWS */
WITH cte AS
(
SELECT
master.composer AS master_composer,
alib.rowid AS arowid
FROM alib
INNER JOIN
master ON hex(alib.__path) = hex(master.__path)
AND alib.l_title = lower(master.title)
AND alib.composer != master.composer
AND length(alib.composer) != length(master.composer)
AND master.composer LIKE '% %'
AND alib.composer NOT LIKE '% %'
)
SELECT * FROM cte;
WITH cte AS
(
SELECT
master.composer AS master_composer,
alib.rowid AS arowid
FROM alib
INNER JOIN
master ON hex(alib.__path) = hex(master.__path)
AND alib.l_title = lower(master.title)
AND alib.composer != master.composer
AND length(alib.composer) != length(master.composer)
AND master.composer LIKE '% %'
AND alib.composer NOT LIKE '% %'
)
UPDATE alib
SET composer =
(
SELECT cte.master_composer FROM cte WHERE cte.arowid = alib.rowid
)
WHERE alib.rowid IN (SELECT arowid FROM cte);
SELECT * FROM alib;
DROP TABLE IF EXISTS alib;
DROP TABLE IF EXISTS master;
Testing Results
The extracted data :-
alib table after UPDATES :-

SQL Server can't execute

There is a problem in my database when I execute this:
<asp:SqlDataSource ID="SqlDataSourceCombine" runat="server"
ConnectionString="<%$ ConnectionStrings:DefaultConnection %>"
DeleteCommand="DELETE FROM [Product] WHERE [ProductId] = #ProductId"
InsertCommand="INSERT INTO [Product] ([ProductName], [ProductDescription], [ProductCategory], [ProductBrand], [ProductPrice], [ProductQty], [ProductUploadDate]) VALUES (#ProductName, #ProductDescription, #ProductCategory, #ProductBrand, #ProductPrice, #ProductQty, #ProductUploadDate)"
SelectCommand="SELECT Product.*, ProductCategory.*, ProductBrand.*
FROM Product
INNER JOIN ProductCategory AS PC ON Product.ProductCategory = ProductCategory.CategoryId
INNER JOIN ProductBrand AS PB ON Product.ProductBrand = ProductBrand.BrandId"
UpdateCommand="UPDATE [Product] SET [ProductName] = #ProductName,
[ProductDescription] = #ProductDescription,
[ProductCategory] = #ProductCategory,
[ProductBrand] = #ProductBrand,
[ProductPrice] = #ProductPrice,
[ProductQty] = #ProductQty,
WHERE [ProductId] = #ProductId">
</asp:SqlDataSource>
I get this error:
You have multiple mistakes in your queries specified.
First your SELECT query uses Product just before last inner join which is wrong syntax. So, use the following query for select command.
SELECT query
SELECT product.*,
productcategory.*,
productbrand.*
FROM product
INNER JOIN productcategory
ON product.productcategory = productcategory.categoryid
INNER JOIN productbrand
ON product.productbrand = productbrand.brandid
Second, your UPDATE query has a comma just before WHERE which again is wrong syntax. Use query below for update command.
Update query
UPDATE [product]
SET [productname] = #ProductName,
[productdescription] = #ProductDescription,
[productcategory] = #ProductCategory,
[productbrand] = #ProductBrand,
[productprice] = #ProductPrice,
[productqty] = #ProductQty
WHERE [productid] = #ProductId
Your final markup should be as below.
SqlDataSource with corrected queries
<asp:SqlDataSource ID="SqlDataSourceCombine" runat="server" ConnectionString="<%$ ConnectionStrings:DefaultConnection %>"
DeleteCommand="DELETE FROM [Product] WHERE [ProductId] = #ProductId"
InsertCommand="INSERT INTO [Product] ([ProductName], [ProductDescription], [ProductCategory], [ProductBrand], [ProductPrice], [ProductQty], [ProductUploadDate]) VALUES (#ProductName,
#ProductDescription, #ProductCategory, #ProductBrand, #ProductPrice, #ProductQty, #ProductUploadDate)"
SelectCommand="SELECT product.*, productcategory.*,
productbrand.* FROM product
INNER JOIN productcategory
ON product.productcategory = productcategory.categoryid
INNER JOIN productbrand
ON product.productbrand = productbrand.brandid "
UpdateCommand="UPDATE [product]
SET [productname] = #ProductName,
[productdescription] = #ProductDescription,
[productcategory] = #ProductCategory,
[productbrand] = #ProductBrand,
[productprice] = #ProductPrice,
[productqty] = #ProductQty
WHERE [productid] = #ProductId ">
</asp:SqlDataSource>

SQlite delete inner join

I have read alot of other answers but cannot get this working!.
select * from invTypes
inner join invGroups on invtypes.groupID = invgroups.groupID
where invGroups.categoryID = 25;
I simply want to delete the record from invTypes if the category ID matches to 25
Would be very grateful of assistance
I have already tried:
delete from invTypes
inner join invGroups on invtypes.groupID = invgroups.groupID
where invGroups.categoryID = 25;
Gives error:
near "inner": syntax error:
DELETE FROM invTypes
WHERE groupID in ( SELECT groupID FROM invGroups INNER JOIN invTypes ON (invGroups.groupID = invTypes.groupID)
WHERE invGroups.categoryID = 25);
Gives:
ambiguous column name: groupID: DELETE FROM invTypes
WHERE groupID in ( SELECT groupID FROM invGroups INNER JOIN invTypes ON (invGroups.categoryID = invTypes.categoryID) WHERE invGroups.categoryID = 25);
you can use delete with a where clause
delete from invTypes
where groupId in ( select groupId from invGroups where CategoryID =25)
DELETE invTypes
FROM invTypes
INNER JOIN invGroups
ON invTypes.groupID = invGroups.groupID
WHERE invGroups.categoryID = 25;

How to modify Active Server Page

I have done an Active Server Page. It is running on a foyerdisplay. The ASP is displaying meetings on that Display. I limited the displaying meetings to 10. The display can display 5-6 meeting at a time. What i want is that if the display is filled with the first 6 meetings the display should "change" to a second page which displays the last 4 meeting. That should happen every 10 seconds. 10 Seconds the first 6 meetings, 10 seconds the 4 meetings and so on. How can I do that?
My Code so far:
<table cellpadding="0" style="table-layout:fixed;width:800px;">
<tr height="15"> <td colspan="6" class="underline"></td> </tr>
<colgroup>
<col style="width:830px" >
</colgroup>
<tr><td> </td></tr>
</table>
<table cellpadding="0" border = "1" style="background-color:white; dotted black;border-collapse:collapse;table-layout:fixed;width:1270px;">
<colgroup>
<col style="width:445px" >
<col style="width:275px" >
<col style="width:125px" >
<col style="width:125px" >
<col style="width:150px" >
<col style="width:150px" >
</colgroup>
<br></br>
<tr style="background-color:blue; height="50">
<th align="left">Seminartitel</th>
<th align="left">Zusatz-Info</th>
<th align="absmiddle">von</th>
<th align="absmiddle">bis</th>
<th align="absmiddle">Gebäude</th>
<th align="absmiddle">Raum</th>
</tr>
<%
set rs=Server.CreateObject("ADODB.recordset")
set rsRaum=Server.CreateObject("ADODB.recordset")
rs.Open "select distinct buchung_id, von, bis, abteilung, veranstalter, THEMA, THEMA_ENABLED " & _
" from RESERVIERUNGRAUM r " & _
" ,BUCHUNG b " & _
" where r.BUCHUNG_ID = b.ID " & _
" and von >= convert(date, getdate(), 4) " & _
" and von < convert(date, dateadd(day,1, GETDATE()), 4) " & _
" and BIS >= getdate() " & _
" and STORNO is null " & _
" order by von, bis" _
,objConn
' Anzahl der darzustellenden Veranstaltungs-Zeilen
lineMax = 10
lineCount = 1
color = "color1"
do until rs.EOF
' Buchungen anzeigen oder nicht
rsRaum.open "select DISPLAY_ENABLED from Buchung where ID = " & rs("buchung_id"), objConn
displayanzeige = rsRaum("DISPLAY_ENABLED")
rsRaum.close
' Hole für lfd. Buchung aus erster Reservierung Raum ID und Indikator für Kopplung
rsRaum.open "select raum_id, KOPPELBESTUHLUNG_ID from RESERVIERUNGRAUM where buchung_id = " & rs("buchung_id"), objConn
raum_id = rsRaum("raum_id")
KOPPELBESTUHLUNG_ID = rsRaum("KOPPELBESTUHLUNG_ID")
rsRaum.close
'Gebäude
rsRaum.open "select distinct g.BEZEICHNUNG " & _
"from GEBAEUDE g, ETAGE e, RAUM r " & _
"Where g.ID = e.GEBAEUDE_ID and e.GEBAEUDE_ID = r.GEBAEUDE_ID and r.ID = " & raum_id, objConn
GebaeudeBezeichnung = rsRaum("BEZEICHNUNG")
rsRaum.close
'Hole Terminal Hinweistext
rsRaum.open "select KSTR from Buchung where ID = " & rs("buchung_id"), objConn
Hinweistext = rsRaum("KSTR")
rsRaum.close
' falls Kopplung, hole ID des "Parent"-Raumes
if not isNull( KOPPELBESTUHLUNG_ID ) then
rsRaum.open "select parent_id from KOPPELN where CHILD_ID = " & raum_id, objConn
if not rsRaum.EOF then
raum_id = rsRaum("parent_id")
end if
rsRaum.close
end if
' hole Raum Details
rsRaum.open "select bezeichnung from Raum where ID = " & raum_id, objConn
raumname = rsRaum("bezeichnung")
rsRaum.close
' Beende, falls Display voll
If lineCount > lineMax Then
exit do
End If
' optionale Unterdrückung der Titelanzeige
if ucase( rs("thema_enabled") ) = "Y" or isnull(rs("thema_enabled")) then
thema = rs("thema")
else
thema = ""
end if
if ucase(displayanzeige) = "Y" or isnull(displayanzeige) then
%>
<tr "margin-bottom:100px" height="70" valign="top">
<td style="overflow:hidden;" class="<% =color%>"><% =thema %></td>
<td class="<% =color%>"><% =Hinweistext %></td>
<td align="center"; class="<% =color%>"><% =FormatDateTime( rs("von"), 4)%></td>
<td align="center"; class="<% =color%>"><% =FormatDateTime( rs("bis"), 4) %></td>
<td align="center"; class="<% =color%>"><% =GebaeudeBezeichnung %><br></td>
<td align="center"; class="<% =color%>"><% =raumname %><br></td>
</tr>
<%
' jede zweite Zeile mit anderer Schriftfarbe
If lineCount mod 2 = 1 Then
color = "color2"
Else
color = "color1"
End If
lineCount = lineCount + 1
end if
rs.moveNext
loop
rs.close
%>
How can I modify my Code?
Create a duplicate page and pass a parameter (GET or POST) to it as RemainingItems from current page. RemainingItems here is 4 and change the current page as following:
If lineCount > lineMax Then
TO be:
If lineCount > firstPageItems Then
obviously:
lineMax = firstPageItems + RemainingItems
For switching between pages, in specific intervals, you should use JavaScript timer on both pages. After time elapsed, redirect the client to the other page (each page knows the address of the other).
It is possible to do all the work in one page but since it need more work, according to question I suggest this one.

How to display data in table using asp.net

Could you help to give me the sample for display data in table using asp.net.
I using this SQL query:
SELECT
pvt.CityName,
pvt.[Deluxe Class],
pvt.[Superior Class],
pvt.[Standard Class]
FROM
(SELECT
c.CityName,
h.HotelName,
tc.TourClass
FROM
tblCity2 c
LEFT JOIN
tblTourHotel2 th ON c.CityID = th.CityID
LEFT JOIN
tblHotel2 h ON th.HotelID = h.HotelID
LEFT JOIN
tblTourClass2 tc ON th.TourClassID = tc.TourClassID) t
PIVOT (
MAX(HotelName)
FOR TourClass IN ([Deluxe Class], [Superior Class], [Standard Class])
) AS pvt
and using table:
<table class="TableTour2" border="0" cellSpacing="0" cellPadding="0" width="500">
<tbody>
<tr>
<th scope=col>City</th>
<th scope=col>Deluxe Class</th>
<th scope=col>Superior Class</th>
<th scope=col>Standard Class</th>
</tr>
<%
Dim cnnPH As New System.Data.SqlClient.SqlConnection
Dim drPH As System.Data.SqlClient.SqlDataReader
Dim cmdPH As System.Data.SqlClient.SqlCommand
Try
cnnPH.ConnectionString = ConStr
cnnPH.Open()
cmdPH = New System.Data.SqlClient.SqlCommand("SELECT pvt.CityName, pvt.[Deluxe Class], pvt.[Superior Class], pvt.[Standard Class] " & _
" FROM ( SELECT " & _
" c.CityName, h.HotelName, tc.TourClass " & _
" FROM tblCity2 c " & _
" LEFT JOIN tblTourHotel2 th ON c.CityID = th.CityID " & _
" LEFT JOIN tblHotel2 h ON th.HotelID = h.HotelID " & _
" LEFT JOIN tblTourClass2 tc ON th.TourClassID = tc.TourClassID " & _
" WHERE th.TourID='1' " & _
" ) t " & _
" PIVOT ( MAX(HotelName) FOR TourClass IN ([Deluxe Class], [Superior Class], [Standard Class]) " & _
" ) AS pvt", cnnPH)
drPH = cmdPH.ExecuteReader
While drPH.Read
%>
<tr>
<th class=sub><%Response.Write(drPH("CityName"))%> </th>
<td><% Response.Write(drPH("HotelName"))%></td>
<td><% Response.Write(drPH("HotelName"))%></td>
<td><% Response.Write(drPH("HotelName"))%></td>
</tr>
<%
End While
drPH = Nothing
cnnPH.Close() : cnnPH = Nothing
Catch ex As Exception
MsgBox(ex.Message)
drPH = Nothing
cnnPH.Close() : cnnPH = Nothing
End Try
%>
</tbody>
</table>
Sorry for something wrong because I am not good with SQL and asp.net program.
I am waiting for your help
many thanks
Kosal
Don't loop like that. Keep code out of the markup. Look into using a GridView or ListView or one of the other DataBound controls.

Resources