Click here to monitor SSC
  • Av rating:
  • Total votes: 12
  • Total comments: 8
Joe Celko

Mimicking Network Databases in SQL

26 September 2011

Unlike the hierarchical database model, which created a tree structure in which to store data, the network model formed a generalized 'graph' structure that describes the relationships between the nodes. Nowadays, the relational model is used to solve the problems for which the network model was created, but the old 'network' solutions are still being implemented by programmers, even when they are less effective.

“Hey, I can write FORTRAN in any language”
-Anonymous

When I tell people that they are writing sequential file system code or Network Database code in SQL, they insist that they cannot be guilty because they never worked with those kinds of data processing. In a previous article, I showed an example from a forum posting of a tape file implemented in SQL (Mimicking Magnetic Tape in SQL). In fact, at the time I am writing this I just saw a forum posting where the poster was having trouble with a procedure:

  1. Use an integer (n) as the parameter. It is how many day ago to archive.
  2. computed (n) days back from the input date and put it in a local variable.
  3. Checked to see if a table for archives existed or not (Hey, people can dismount a tape, so you always checked the tape label before you write to it).
  4. Insert rows from the base table into the archive table. Replace “row” with “record” and “table” with “tape” and you have a classic tape file operation. Oh, the old IBM tape labels were “yyddd” from the system clock. There are good Y2K stories about that, but I digress.
  5. Delete the inserted rows from the base table (aka Master tape or punch card deck)

See the physical movement of punch cards from deck to another? It never occurred to the poster to simply have a status column in the table, which has 'archive” as a possible value. A simple update everything in the procedure and we do not need a local variable to hold the computation, like we did in COBOL or assembly language.

UPDATE Foobars

SET foobar_status

WHERE creation_date <= DATEADD (D, -ABS(@in_day_back), CURRENT_TIMESTAMP);

The ABS() is a safety in case we get a negative input.

A similar, but more complicated problem, is seeing a Network Database in disguise. The first problem is that commercial products were all different. And they all used different terms. ANSI X3H2, the Database standards committee, created a CODASYL Standard that became the NDL language. The hope was that NDL would be a reference model to get the product terminology aligned. But nobody used it. In ANSI X3H2, we approved it, forgot it and let it expire while we went to work on SQL. I might have one of the few existing copies of the NDL standard in the world; if anyone has a Gütenberg Bible, I will trade.

Network Database Basics

Network Databases use pointers. A lot of current IT people have never worked with pointers. Their languages hide them from the programmer and do all the garbage collection and dirty work for them. And in SQL, the closest thing we have is a reference, which is not a pointer.

In the simplest terms a pointer is a languages construct that resolves to a PHYSICAL address in storage. Notice that I did not say if that was primary or secondary storage. And I did not define what “resolves” means. Yes, it can be primary or secondary storage, with data pages swapping in and out of virtual memory. But resolution is a little trickier. In low level languages, a pointer simply gets you to a position on the data page, but you have no idea what it is pointing at. The program decides upon arrival. Higher level languages have pointers that are declared as to their targets, which can be simple data types (“pointer to integer”, “pointer to string”, etc.) or whole records (“pointer to parts record”). The Network Databases were based on record pointers.

The terminology “link”, “parent”, “master”, “child” and so forth all come from Network Databases. They are not part of RDBMS, but you will find new (or bad) SQL programmers inventing terms like “parent table” or “link table” because they never left a Network Database mindset.

These tools have a NEW() function to create a new, unused pointers as needed and a NIL pointer (not NULL!), which is a pointer to nothing, an end of the chain of links. To navigate the pointer chains, we also have a NEXT function that uses the pointer value to get the next record in the chain.

The target of a pointer can be changed or deleted. Two pointers could have the same target. Basically, anything you can draw with boxes and arrows can be done with pointers. Hey, why don't we draw some boxes and arrows! I will use Chris Date's classic “Suppliers & Parts” Database for these examples.

Here is a simple linked list of parts. You can start at the “Bolt”, invoke the Next() procedure and get the “Nut”; invoke Next() again and get the “Washer”; invoke Next() again and you a message that you hit a NIL, then end of the chain. You are navigating this network, procedurally.

The real power is when you have more pointers in a record. Going back to the suppliers-and-parts. Let's put parts as children to suppliers as parents. That would look like this:

Each node has two pointers. This actually the structure used in the LISP language, with the names CAR (pronounced “car”, short for “contents of A register”) and CDR (pronounced “cudder”, short for “contents of C register”). The weird names come from the original hardware of the first implementation. They are the head and the tail respectively of a list.

What did you notice about this structure? It is quick and easy find a Supplier by going from tail to tail until you find who you wanted. You then go down the head chain to find the parts from that supplier. Bad news: If I want to find all the suppliers who stock washers, I still have to chase down the parts chain of each supplier. I also cannot go back up the chain.

I can also make a circular list, letting you get back to the start of a list by looping around.

You can get around this problem with a double linked list. It has a extra pointer in each node that goes back to the prior node in the chain.

 Different pointers can have the same target, so there is only one occurrence of a node in the system with many references to it.

I can also create nodes with multiple pointers and kinds of things. It can get complicated. And it is fragile. When I delete a node, I have to take pointer and make it the pointer of the prior node the chain and leave the deleted node as an orphan floating in the storage space. If a link is broken, restoring it can be a problem.

Many decades ago I worked for a bank that paid employees by starting a free checking account and making deposits to it. The checking database was a hierarchy which started with wholesale (commercial) and retail (consumer) accounts, then broke retail into internal (employees) and external accounts. The internal accounts were then broken down by department and then you finally got to the actual account. The department for which I worked was sold when banks were no longer allowed to compete with timeshare computing companies.

I went to a branch bank to see if I had gotten my final check (no on-line banking back then). The system crashed. The system crashed every time I asked for the next week. My former department had been deleted and the pointer chain was broken. It never occurred to anyone that a department would disappear while it still had valid accounts in it.

The utility programs for Network Databases had to do garbage collection and restore broken links, or misplaced links (parent Account A gets a bad link and sudden has the children of Account B).

Faking Network Database in SQL

Just as programmers mimicking tape files used IDENTITY for a sequential record number, the “Network Mimic” uses GUIDs, UNIQUEIDENTIFIER and NEWID(). It is no coincidence that NEWID() looks like the NEW() pointer function in a Network model.

Let me look at a forum posting that demonstrates the Network mindset in action. I had to provide the DDL, since the poster did not. In fact, he has a NULL-able column as a Primary Key in his narrative, so it will not compile.

CREATE TABLE TBL_Events (
event_id UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
location_id UNIQUEIDENTIFIER
  REFERENCES TBL_Locations (Location_id),
notes_txt VARCHAR (500));


CREATE TABLE TBL_Locations (
event_id UNIQUEIDENTIFIER NOT NULL
  REFERENCES TBL_Events (event_id),
location_id UNIQUEIDENTIFIER NULL PRIMARY KEY,
notes_txt VARCHAR (500));

Yes, he put the “TBL-” prefix on the table names. Since Network Databases could have many different storage structures, the engine needed to know what was what. In SQL,this is redundant as well as a violation of ISO-1179 rules. We only have tables and they are in limited flavors. Yes, both his tables have the same columns.

To quote the posting: ..

>> “Locations is the parent table with a relationship to events through Location ID.” <<

See the word “parent” instead of the SQL “Referenced” and “Referencing” tables?

To continue: ...

>> Location_ID is set to be NewID() on create in Locations, and Event_ID is set to be NewID() on create in events. <<

This is pointers, not keys. GUIDs are not attributes of either events or locations. They have meaning only after you get to the target of the pointer.

>> The table, relationship, and PK format is non-changeable due to organizational policy governing replication. <<

GUIDs for replication instead of keys is a different issue. It is at a higher level than the schema and treats the whole schema and tables as the unit of work without regard to their content.

>> I'm looking for advice on how to define an INSERT TRIGGER that will create a new row in Events, with the location_id pulled from the parent Locations table, and a new unique event_id. E.g., when (by outside application with no ability to embed SQL) a new Locations record is created, it gets a location_id of 8170daed-92c8-47f1-98ca-147800329686, and the trigger creates a new event record also with a location_ID of 8170daed-92c8-47f1-98ca-147800329686 and an event_ID of cfed8fe8-b5be-4f78-b366-008672e39637. <<

Records and not rows. Oh, that's right; Network Databases have records. The mindset always shows up in the terminology you use. What he is trying to do with procedural trigger code is Network navigation. Can you guess where 8170daed-92c8-47f1-98ca-147800329686 is on a map? I use (longitude/ latitude) or HTM (hierarchical triangular mesh) instead; both are industry standard, verifiable with the GPS on my cell phone and reproducible. Likewise, an event should have a name that a human being can understand. And they will both be shorter than GUID.

The idea that an event is BOTH an entity and an attribute of a Locations is absurd. The Events and the Locations have a relationship. What he is trying to build is a double linked list mechanism that would be part of a Network Database engine.

The right way to do this is:

-- entity
CREATE TABLE [Events] (
event_id CHAR(15) NOT NULL PRIMARY KEY,
observation_txt VARCHAR (500));
-- entity
CREATE TABLE Locations (
location_htm CHAR(18) NOT NULL PRIMARY KEY,
observation_txt VARCHAR (500));
-- relationship
CREATE TABLE Event_Calendar (
event_id CHAR(15) NOT NULL
  REFERENCES [Events](event_id)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
location_htm CHAR(18) NOT NULL
  REFERENCES Locations(location_htm),
event_start_date DATE NOT NULL,
event_end_date DATE NOT NULL,
  CHECK (event_start_date <= event_end_date),
PRIMARY KEY (event_id, location_htm));

Notice that relationship has its own attributes, such as the time slot in which it occurs. I decided that this is a one-to-one relationship; the poster didn't tell us. I can change this to one-to-many or a many-to-many relationship by changing the PRIMARY KEY. Try doing that in a Network Database! The above schema is easy to search by either location or by event. This is one many reason RDBMS beat out the navigational model of data.

"Perfecting oneself is as much unlearning as it is learning."
-- Edsgar Dijkstra
Joe Celko

Author profile:

Joe Celko is one of the most widely read of all writers about SQL, and was the winner of the DBMS Magazine Reader's Choice Award four consecutive years. He is an independent consultant living in Austin, TX. He has taught SQL in the US, UK, the Nordic countries, South America and Africa.
He served 10 years on ANSI/ISO SQL Standards Committee and contributed to the SQL-89 and SQL-92 Standards.
He has written over 800 columns in the computer trade and academic press, mostly dealing with data and databases. He is the author of eight books on SQL for Morgan-Kaufmann, including the best selling SQL FOR SMARTIES.
Joe is a well-known figure on Newsgroups and Forums, and he is famous for his his dry wit. He is also interested in Science Fiction.

Search for other articles by Joe Celko

Rate this article:   Avg rating: from a total of 12 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: Surrogate keys and coordinates
Posted by: Seven24 (view profile)
Posted on: Wednesday, September 28, 2011 at 11:12 AM
Message: I'm not sure I buy your argument that event_id is a pointer and not simply a surrogate key: an arbitrary, system generated value that identifies each instance of an event. No question, there needs to be *another* human discernible uniqueness constraint and perhaps we are not seeing the entire table schema but I bet that the original developer was creating the event_id to be a surrogate key.

*Can you guess where 8170daed-92c8-47f1-98ca-147800329686 is on a map?*

A silly argument. You always seem to ignore the availability of the data in your analysis. Using longitude and latitude to identify each location is likely an expense (of time, resources, etc) that was not seen as worth the effort. An address and a room might fit the bill *as an additional* identifying piece of information rather than coordinates but in addition to the surrogate key. Why the surrogate key? They make relationships substantially easier to physically create and manage than having many columns be required as part of the foreign key relationship. It should also be noted that an address and a room will likely be longer than a guid.

RE: Event_id as a char(15)?!

What a terrible choice for a key. First, by using a char(15), you require the user derive a unique name for the event which with many thousands of events becomes a trial and error exercise ("Does this work? No? How about this? No? How about this?...). Second, you must deal with the nonsense of padded spaces which is fun in queries. Third, your key doesn't handle a name change for the event so you end up with a key that to a human in no way relates to the actual event itself. Fourth, what happens when 15 characters isn't enough? You have to expand the key. Whoa, slow down there Tex. That means you have to drop all the relationships and any other dependencies, expand the key, expand the foreign key columns and then re-create the relationships and any other dependent objects. If instead, the primary key were a surrogate key with a name that also has a unique constraint, you could easily expand the size of the name column without affecting the relationships, without orphaning the meaning of the key due to a change in the event name and guarantee that your event names are unique and thus discernible by a human. It's as if there is a reason people use surrogate keys or something.

Subject: Think, research and then code
Posted by: Celko (view profile)
Posted on: Wednesday, September 28, 2011 at 8:54 PM
Message: >> I'm not sure I buy your argument that event_id is a pointer and not simply a surrogate key: an arbitrary, system generated value that identifies each instance of an event. <<

You might want to read Dr. Codd's definition of a surrogate key. It has to be
1. generated by the system (GUID, IDENTITY meet this one)
2. hidden from the user (they fail on this one)
3. they come from the data values and not the hardware (they fail on this one)
4. they are not repeatable

What you are taking about is an exposed locator that might be an auto-increment, IDENTITY, GUID, RowID (Oracle; it decodes to an curtail cylinder and track)

>> A silly argument. You always seem to ignore the availability of the data in your analysis. Using longitude and latitude to identify each location is likely an expense (of time, resources, etc) that was not seen as worth the effort.<<

I run a cell phone app and get (longitude, latitude). I use a SAN (Standard Address Number) if my industry has one, or the FedEx codes, etc What time and expense? I download that stuff. What I cannot do is find a GUID or IDENTITY when I am not in my one database on my one machine. This is why the DMV, insurance industry, CarFax, auto industry, etc. all use the VIN.

Remember Codd's 12 rules? The ones about physical independence and distributed Databases?

>> .They make relationships substantially easier to physically create and manage than having many columns be required as part of the foreign key relationship. It should also be noted that an address and a room will likely be longer than a GUID. <<

When I did my book on Standards, I found that most of the encoding schemes are shorter than a GUID
(16 bytes is one credit card number), SAN, DUNS, ISBN, UPC, ICD, etc are not only shorter,m have a check digit and/or validation process along with universal verification. Saving typing is not a good argument in this day and age; my text editor does that stuff with a macro

>> RE: Event_id as a CHAR(15)?! What a terrible choice for a key.<<

That is the size of a TicketMaster event code, as I recall. That is why I picked it; if it were a real client, I would have also found out about the check digit, verify the length, validation . Seems to work okay for them :) If I use a name that might be on a mailing label, then I use VARCHAR(35) based on the USPS 3.5 inch mailing label and 10 pitch monofont printers.

>> First, by using a CHAR(15), you require the user derive a unique name for the event which with many thousands of events becomes a trial and error exercise ("Does this work? No? How about this? No? How about this?...). <<

See the difference in a database mindset and an application mindset? The DB guy first looks for industry standard identifiers. Application guys start coding immediately. It is a hell of lot quicker to type “g-u-i-d” than to interview the clients, learn their industry, go to ANSI and ISO websites, etc. I seldom invent a key; I discover it.

The nice part of about industry standards is that they are fairly constant and universal. CASCADE options do most of the work when a standard identifier changes. When an industry standard does change size, there is a pattern and external support. The book industry went from ISBN-10 to ISBN-13 a little while back, US retail went from UPC to EAN as part of the same upgrade.

The bad news in the T-SQL world is that a reference actually duplicates a value in the referencing table. Other products build pointer chains back to the PK/UNIQUE value in the referenced table. To change the data type of the column, you do a single, ugly ALTER with CASCADE statement and re-index everything. Of course any DML is now suspect.

Subject: A bit more history
Posted by: BuggyFunBunny (view profile)
Posted on: Thursday, September 29, 2011 at 10:05 AM
Message: the network "model" pre-dates the hierarchical, which is counter-intuitive, in that network is more flexible (in a stiff sort of way) than the hierarchical. the reason appears to be that IBM didn't want to buy into the de facto standard (the first network database was either at Goodrich, of tire fame, or General Electric of SNL fame). so IMS was born. reactionary devolution was around in the 1960s.

the other point, which to my reading isn't obvious enough, is that the network structure is baked in, and requires re-programming if changed. done stupidly, RDBMS may too, but not by the rules. by the rules, a network database structure update is not trivial.

Subject: Think about more than theory; consider how it will work in practice.
Posted by: Seven24 (view profile)
Posted on: Thursday, September 29, 2011 at 3:09 PM
Message: RE: Surrogate Keys
>> 2. hidden from the user (they fail on this one)

***Which user***? If you mean the *end* user of the system that communicates with the database through an application, there is nothing to indicate that the developer planned to show the surrogate key to the user. If you mean any user include the developer themselves, then by that definition very concept of a surrogate key is akin to Russell's teapot and has no meaning. Yet, the solution of using a key that isn't visible to the *end* user but is used by developers is so common that I would bet it exists in 99% of all databases ever designed.

>> 3. they come from the data values and not the hardware (they fail on this one)

Don't buy it. Every definition of a surrogate I've seen over the past 20+ years implies it is system generated independently of the attributes of the row itself. Your definition would make it impossible for such a concept to exist beyond a concatenation or hashing of the attributes themselves.

>> I run a cell phone app and get (longitude, latitude). I
>> use a SAN (Standard Address Number) if my industry
>>has one, or the FedEx codes, etc What time and expense?
>> I download that stuff.

From what you have described, we are talking about addresses. It isn't clear whether longitude and latitude is necessary or even useful given that it will add complexity. You have to setup the schema to store those, find a service to query for it, code the application to handle exceptions and failures in the service and so on. All that is likely unneeded and does not add value to the customer. In fact, address standardization may not be needed at all.

>This is why the DMV, insurance industry,
>CarFax, auto industry, etc. all use the VIN.

The DMV also uses an arbitrary number to identify licensed drivers of which the only true means to validate its correctness is to query their central database and compare it with what is on the license itself. Further, there is nothing in the spec that says whether the addresses must be mailing addresses. "By the statue in Elm Park", "The parking lot behind Shay Stadium", "The Mall in Washington" could be locations for events and longitude and latitude in those scenarios could be off wildly beyond likely being unnecessary. If the spec calls for using longitude and latitude then fine. However, most systems that store a list of addresses do not have this requirement.

>> I found that most of the encoding schemes are shorter than a GUID

Operative word: encoding schemes. That requires that said scheme exists and is available at time of entry. Often, they are not nor can be relied upon to be unique (e.g. ISBN numbers).

>> That is the size of a TicketMaster event code...

Actually, that code (or one of the ones I remember using when interacting with some ticket agency which I thought was TM) is a random collection of alphanumeric characters that can only be verified against TicketMaster's system. That blows your "location independence". To be truly independent, the event itself or an independent third-party would need to provide and manage the codes used to identify the events.

>> See the difference in a database mindset and an
>> application mindset? The DB guy first looks for
>> industry standard identifiers. Application guys
>> start coding immediately.

No. The *system" mindset it to consider the design of the database in the context of the entire system, not just in isolation. Thus, I would immediately see that either the user would be require to derive a magic code to identify their event or (more likely) the developers would be require to come up with an algorithm to randomly generate that code (actually, generate, try, generate, try until it found a code that was unique) and if that is the case, you might as well use a surrogate key behind the scenes. It comes down to the requirements. Is a short code that represents the event a requirement? It may not be.

>> The nice part of about industry standards is that they are fairly constant and universal.

Then you and I work in entirely different worlds. My experience is that there are generally very few codes that are reliable to be unique and are available at time entry. I'm not talking about currencies and languages and such. I'm talking about general concepts like people (not customers, just lists of people), films (no standard actually is in use everywhere or even most places. ISAN definitely not), contracts (not everyone creates unique stamps on their contracts. many that do stamp their contracts have nothing to ensure they are unique), territories (not countries. arbitrary geographical areas such as "South East Asia"), worldwide companies many which do not have a DUNS number and I could go on. *When* they are available, like currencies and languages, ISO or industry codes are great.

>> CASCADE options do most of the work when a standard identifier changes.

Cascade won't help you. Cascade only works when the *value* changes; it does not work when the schema of the value changes. In every db I've seen, you have to drop some or all the dependencies to alter the size of the PK column. That's a royal pain and a needless one IMO.

While it's true everyone "changed" to ISBN-13, I wonder how many of those systems had the ISBN value as an attribute rather than the primary key of their respective tables. I bet most systems had it as an attribute (perhaps with a unique constraint) with a system generated key. Same with UPC to EAN. It illustrates the difference between theory and practice. Yes, in theory for a table of books you should be able to make the PK the ISBN number. In practice, you find that there are duplicates (especially with older titles) and altering the scheme of the PK is a unnecessary pain.

Subject: More history
Posted by: Celko (view profile)
Posted on: Monday, October 10, 2011 at 8:12 PM
Message: >>the first network database was either at Goodrich, of tire fame, or General Electric of SNL fame <<

The first one I worked with from the start of a project was Image/3000 which was a port of TOTAL to the HP-3000. This one had Master sets that were hashed, so you had to pre-allocate a prime number of slots. Then each master record could have a chain of slave records. I think you could go backwards in the chain.

This lead to a very rigid design and some strange tricks. You would traverse to a slave that had the record number of a second Master so you could get to a second slave. That is how you faked more than one level of depth in a tree. Something as simple as Customer -> Orders -> Order Details was nested loops and local variables to track.

Subject: More on driver's license numbers and addresses.
Posted by: Celko (view profile)
Posted on: Monday, October 17, 2011 at 2:44 PM
Message: >> The DMV also uses an arbitrary number to identify licensed drivers of which the only true means to validate its correctness is to query their central database and compare it with what is on the license itself. <<

No, each state has different algorithms. In fact, that was a running topic in theh MATHEMATICS MAGAZINE (Mathemtical Association of America) several years Did you know that New Jersey uses your eye color? That Utah assigns an eight-digit driver's license number in sequential order with a MOD 10 check digit. Newfoundland uses a similar scheme. IBM developed schemes for several states. Etc. I do not know of any that are random. The push for a natiional scheme for voter registration and biomerics seems to have faded

>> Further, there is nothing in the spec that says whether the addresses must be mailing addresses. "By the statue in Elm Park", "The parking lot behind Shay Stadium", "The Mall in Washington" could be locations for events and longitude and latitude in those scenarios could be off wildly beyond likely being unnecessary. <<

The format for all addresses in the US follow the rules for the 9-1-1 System. This is NOT "nine -eleven"; this system is part of the national emergency phone system. It was a big deal in Texas because so many of the rural addresses were based on rural roads, farm and ranch naems, etc. Now, a venue would be the things you gave.

Subject: RE: Driver's license numbers and addresses
Posted by: Seven24 (view profile)
Posted on: Thursday, October 27, 2011 at 12:26 AM
Message: > No, each state has different algorithms.

I was specifically referring to a DMV within a given State rather than all DMVs.

> In fact, that was a running topic in theh
> MATHEMATICS MAGAZINE (Mathemtical Association of America)
> several years
> Did you know that New Jersey uses your eye color?

Utterly stupid. I guess they haven't heard of colored contacts?

> That Utah assigns an eight-digit driver's
>license number in sequential order with a MOD 10 check digit.
> Newfoundland uses a similar scheme. IBM developed schemes
> for several states. Etc. I do not know of any that are random.
>The push for a natiional scheme for voter registration and biomerics seems to have faded

You have proved my point. That is an arbitrary number derived from within the DMV's system rather than from an amalgam of attributes about the person such as a VIN. You should have stuck with NJ. My point is that the DMV's database is the authoritative system and it is orders of magnitude simpler for that system to simply auto-generate a value rather than try to derive a magic value amalgamated from the malleable attributes of the person.

I wonder how often that check digit is actually used these days. Back in the day, when making a request directly against the DMV system was logistically expensive, I can see the benefit in mitigating mistyped values. However, now systems are connected. You really don't save much in coding that check digit validation over simply querying the authoritative system directly.

> The format for all addresses in the US follow the rules for the 9-1-1 System...

It all comes down to how the data will actually be used. If it will be used to send snail mail, then yes, having a USPS recognized address (assuming we're in the US) is a good thing. However, for something as arbitrary as events, that may not be needed. "Conference Room 5" might a location.

Subject: From a Filesystem Ninja ; p
Posted by: jiltgeisd (view profile)
Posted on: Sunday, October 21, 2012 at 2:35 PM
Message: Hello Mr. Celko,

Thank you for this truly wonderful article. As a relative newcomer to SQL and Databases in general, and coming from a background in the BSD Unix and the Berkeley DB school of thought and way of thinking, this makes great sense to me in knowing how to approach SQL and how NOT to.


 

Phil Factor
Searching for Strings in SQL Server Databases

Sometimes, you just want to do a search in a SQL Server database as if you were using a search engine like Google.... Read more...

 View the blog

Top Rated

SQL Server XML Questions You Were Too Shy To Ask
 Sometimes, XML seems a bewildering convention that offers solutions to problems that the average... Read more...

Continuous Delivery and the Database
 Continuous Delivery is fairly generally understood to be an effective way of tackling the problems of... Read more...

The SQL Server Sqlio Utility
 If, before deployment, you need to push the limits of your disk subsystem in order to determine whether... Read more...

The PoSh DBA - Reading and Filtering Errors
 DBAs regularly need to keep an eye on the error logs of all their SQL Servers, and the event logs of... Read more...

MySQL Compare: The Manual That Time Forgot, Part 1
 Although SQL Compare, for SQL Server, is one of Red Gate's best-known products, there are also 'sister'... Read more...

Most Viewed

Beginning SQL Server 2005 Reporting Services Part 1
 Steve Joubert begins an in-depth tour of SQL Server 2005 Reporting Services with a step-by-step guide... Read more...

Ten Common Database Design Mistakes
 If database design is done right, then the development, deployment and subsequent performance in... Read more...

SQL Server Index Basics
 Given the fundamental importance of indexes in databases, it always comes as a surprise how often the... Read more...

Reading and Writing Files in SQL Server using T-SQL
 SQL Server provides several "standard" techniques by which to read and write to files but, just... Read more...

Concatenating Row Values in Transact-SQL
 It is an interesting problem in Transact SQL, for which there are a number of solutions and... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.