Update Query Timeout on SQL Server View with MS Access - sql

I am having some trouble with updates to an SQL Server View through MS Access. The set of tables used for this is built off of a base table. This base table is of this format.
Id int (not-nullable; auto-assigned)
A1 varchar(50) (nullable)
A2 varchar(50) (nullable)
B1 varchar(50) (nullable)
B2 varchar(50) (nullable)
C1 varchar(50) (nullable)
C2 varchar(50) (nullable)
One row on this table is updated by multiple groups of users in our company. For instance, user group "A" updates columns "A1" and "A2", user group "B" updates columns "B1" and "B2", and so forth. However, we also want to prevent user group "A" from updating the columns of user group "B". To accomplish this, I set up a view containing the columns appropriate for each user group. For instance, the view for user group "A" would only contain the columns "Id", "A1", and "A2". Then I set the "Bind To Schema" option on the views in SSMS to "Yes", and I set up a unique, clustered index on the "Id" column on each of the views. In MS Access, I connect to these views as linked tables using an ODBC connection. When I open the tables in MS Access in design view and check the indexes, it does properly identify the "Id" column as the primary key.
Here is where the trouble comes in: When I try to update a record through MS Access in one of the views, sometimes the update runs instantly, but sometimes the update times out. Here is the error that I get.
"SM_Notes_Bridge" is the actual name of one of my views. Almost all previous answers that I can find online say to increase the amount of time before the update times out in MS Access, which seems like it is not a solution for my problem as the update either runs instantly or times out. There is no middle ground.
Another note is that I am currently the only one using this base table and these views. Also, important systems are developed around that base table structure, so changing its structure will take a lot of convincing.

By creating an unique index on a schema bound view, you're creating an indexed view, also called a materialized view.
A relevant property of indexed views:
When executing DML on a table referenced by a large number of indexed views, or fewer but very complex indexed views, those referenced indexed views will have to be updated as well. As a result, DML query performance can degrade significantly, or in some cases, a query plan cannot even be produced (MSDN).
Thus, creating multiple indexed views on a table that is updated often is a big no-no! Review this MSDN page for further explanation when and when not to use an indexed view. Every insert and update will have to propagate to all the indexed views, and will cause locks on those views as well.
Drop the indexes on ALL views on that table. As far as you've told me, there's no reason at all to use indexed views and they will hurt performance in a major way when executing updates. Even if that didn't fix this issue, it will improve performance.

Related

SQL Direct Reference to Data

Is there a way in Microsoft SQL to reference a specific item of data based on table, column and record?
For example, table A (COL1 INT, COL2 INT) has 2 records (1,2) and (3,4). Can I somehow capture value 4 by reference, rather than as "4"?
The purpose is to allow me to create an audit method that can point to specific value in a (table, column, record) without having to duplicate that value in my audit table (which could be large, therefore bloating my database size).
I am thinking ... just like Object_Id identifies a particular SQL object, so would this reference (some kind of GUID, perhaps?) identify a specific piece of data.
Many thanks in advance.
The answer is No. In MS SQL (and, as far as I know in other popular databases) there are no such references to specific values.
Moreover, even table rows in MS SQL do not have embedded unique identifiers, unless you take care to create an IDENTITY column.
You can yourself make the implementation of such references. For example, create a table with columns
data_id,
table_name,
row_id,
column_name
and fill it up every time you need a reference. Then you can refer to piece of data by data_id.
But this is not a good solution.
in most cases, a single entry in this table will consume more space
than the referenced data value itself
to get the values ​​you still have to use dynamic sql
this will only work for tables that have an IDENTITY column and it
has the same name for all tables
and so on

PostgreSQL many jsonb columns vs many rows

From other answers on many columns vs many rows (or tables) it seems columns are more performant for normalized data. What about serialized data?
I'm going to store many in-progress web forms, i.e. not yet validated just a dump of what the user has so far so they can continue in another session. The forms will be serialized as json and stored in a jsonb column. There are currently ten forms but (many) more will be added in the future.
Is it better to have one column with a user id and a column for each form:
CREATE TABLE "forms" (
"user_id" uuid NOT NULL,
"form_a" jsonb,
"form_b" jsonb,
"form_c" jsonb,
...
)
or many rows with a user uuid, form id, and form json columns:
CREATE TABLE "forms" (
"user_id" uuid NOT NULL,
"form_id" uuid NOT NULL,
"form_json" jsonb NOT NULL
)
I'm sure querying for just one row is faster, but what about updating a column in a row with many jsonb columns? or adding a new jsonb column to a table with millions of rows? At what point does it tip to favoring many rows?
thanks!
If new forms are introduced only during maintenance windows (upgrades), you might get away with using the first method.
If new forms can be introduced during normal operation, that would cause problems:
ALTER TABLE blocks and is blocked by all concurrent data modifying statements, which can be a problem.
You need to be the table owner or a superuser to run ALTER TABLE, but for security reasons it is better if your application user can be somebody else than the table owner.
Increased data volume for UPDATE is not a consideration, because as the documentation says:
During an UPDATE operation, values of unchanged fields are normally preserved as-is; so an UPDATE of a row with out-of-line values incurs no TOAST costs if none of the out-of-line values change.
I think that the second design is cleaner, and the slightly more complicated query will not be noticably more expensive if you have the right indexes.

Difference between a db view and a lookuptable

When I create a view I can base it on multiple columns from different tables.
When I want to create a lookup table I need information from one table, for example the foreign key of an order table, to get customer details from another table. I can create a view having parameters to make sure it will get all data that I need. I could also - from what I have been reading - make a lookup table. What is the difference in this case and when should I choose for a lookup table?? I hope this ain't a bad question, I'm not very into db's yet ;).
Creating a view gives you a "live" representation of the data as it is at the time of querying. This comes at the cost of higher load on the server, because it has to determine the values for every query.
This can be expensive, depending on table sizes, database implementations and the complexity of the view definition.
A lookup table on the other hand is usually filled "manually", i. e. not every query against it will cause an expensive operation to fetch values from multiple tables. Instead your program has to take care of updating the lookup table should the underlying data change.
Usually lookup tables lend themselves to things that change seldomly, but are read often. Views on the other hand - while more expensive to execute - are more current.
I think your usage of "Lookup Table" is slightly awry. In normal parlance a lookup table is a code or reference data table. It might consist of a CODE and a DESCRIPTION or a code expansion. The purpose of such tables is to provide a lsit of permitted values for restricted columns, things like CUSTOMER_TYPE or PRIORITY_CODE. This category of table is often referred to as "standing data" because it changes very rarely if at all. The value of defining this data in Lookup tables is that they can be used in foreign keys and to populate Dropdowns and Lists Of Values.
What you are describing is a slightly different scenario:
I need information from one table, for
example the foreign key of an order
table, to get customer details from
another table
Both these tables are application data tables. Customer and Order records are dynamic. Now it is obviously valid to retrieve additional data from the Customer table to display along side the Order data, and in that sense Customer is a "lookup table". More pertinently it is the parent table of Order, because it has the primary key referenced by the foreign key on Order.
By all means build a view to capture the joining logic between Order and Customer. Such views can be quite helpful when building an application that uses the same joined tables in several places.
Here's an example of a lookup table. We have a system that tracks Jurors, one of the tables is JurorStatus. This table contains all the valid StatusCodes for Jurors:
Code: Value
WS : Will Serve
PP : Postponed
EM : Excuse Military
IF : Ineligible Felon
This is a lookup table for the valid codes.
A view is like a query.
Read this tutorial and you may find helpful info when a lookup table is needed:
SQL: Creating a Lookup Table
Just learn to write sql queries to get exactly what you need. No need to create a view! Views are not good to use in many instances, especially if you start to base them on other views, when they will kill performance. Do not use views just as a shorthand for query writing.

SQL Server Database - Hidden Fields?

I'm implementing CRUD on my silverlight application, however I don't want to implement the Delete functionality in the traditional way, instead I'd like to set the data to be hidden instead inside the database.
Does anyone know of a way of doing this with an SQL Server Database?
Help greatly appreciated.
You can add another column to the table "deleted" which has value 0 or 1, and display only those records with deleted = 0.
ALTER TABLE TheTable ADD COLUMN deleted BIT NOT NULL DEFAULT 0
You can also create view which takes only undeleted rows.
CREATE VIEW undeleted AS SELECT * FROM TheTable WHERE deleted = 0
And you delete command would look like this:
UPDATE TheTable SET deleted = 1 WHERE id = ...
Extending Lukasz' idea, a datetime column is useful too.
NULL = current
Value = when soft deleted
This adds simple versioning that a bit column can not which may work better
In most situations I would rather archive the deleted rows to an archive table with a delete trigger. This way I can also capture who deleted each row and the deleted rows don't impact my performance. You can then create a view that unions both tables together when you want to include the deleted ones.
You could do as Lukasz Lysik suggests, and have a field that serves as a flag for "deleted" rows, filtering them out when you don't want them showing up. I've used that in a number of applications.
An alternate suggestion would be to add an extra status assignment if there's a pre-existing status code. For example, in a class attendance app we use internally an attendance record could be "Imported", "Registered", "Completed", "Incomplete", etc.* - we added a "Deleted" option for times where there are unintentional duplicates. That way we have a record and we're not just throwing a new column at the problem.
*That is the display name for a numeric code used behind the scenes. Just clarifying. :)
Solution with triggers
If you are friends with DB trigger, then you might consider:
add a DeletedAt and DeletedBy columns to your tables
create a view for each tables (ex: for table Customer have a CustomerView view, which would filter out rows that have DeletedAt not null (idea of gbn with date columns)
all your CRUD operations perform as usual, but not on the Customer table, but on the CustomerView
add INSTEAD OF DELETE trigger that would mark the row as delete instead of physically deleting it.
you may want to do a bit more complex stuff there like ensuring that all FK references to this row are also "logically" deleted in order to still have logical referential integrity
I you choose to use this pattern, I would probably name my tables differently like TCustomer, and views just Customer for clarity of client code.
Be careful with this kind of implementation because soft deletes break referential integrity and you have to enforce integrity in your entities using custom logic.

Is this a bad way to structure my Sql Server database?

I have a table that contains a few columns and then 2 final (nullable) columns which are varbinary (actually, they are SQL 2008 geography types, but I want to keep this post database agnostic).
I've hit around 500mb with around 200K rows. The varbinary is the problem - and I need the data.
So, I was wondering if it's bad if I do the following:-
Create a separate FILEGROUP: SpatialData.mdf
Create a new table, assigned to that new filegroup.
Move all the spatial data (read: last two fields) out of the original table and into the new table. The new table has a foreign key against the original table.
Create a view representing both tables.
Now, the view will be a left outer join because the relationship is: the new table has a zero or one row relationship to the original table.
EG.
Original Table
FooId INT PK NOT NULL IDENTITY
Blah VARCHAR(..) NOT NULL
Boo WHATEVER NOT NULL
New Table
FooID PK FK NOT NULL
Spatial_A VARBINARY(MAX)/GEOGRAPHY
Spatial_B VARBINARY(MAX)/GEOGRAPHY
The reason why I want to know if this is bad is because of the view and how the view is doing a join on the spatial table. I'll be using the view a lot. Currently, I'm just doing queries against the original table (because the new table doesn't exist just yet). By adding this join and the PK/FK relationship, will this impact performance?
Why split the data? I need to download the live DB to our dev servers now and then. We don't really care too much about those two spatial fields, so not having them is fine. Therefor, the size of the database to download will be much smaller.
Thoughts?
Instead of creating a second table, joining, and creating a view, a better solution that is possible with SQL Server 2005/2008 is to use table partitioning. To my recollection, you can vertically partition a table, and place some columns (i.e. your geospatial columns) in one file group, while putting the rest in another file group. SQL Server will handle the rest for you, you don't need to bother with a join, and you don't need a view.
The method that you've described is actually fairly common in my experience. Technically, if you were to normalize your database to the fullest extent you would have a lot of tables like that since one of the (usually not used) steps in normalization includes making sure that no columns have NULL values.
In practice it isn't usually carried out to that extent, but for a column (or columns) that is sparsely populated it's not a bad idea to separate it out. As long as the tables share the same primary key (which will of course be indexed), performance shouldn't be a problem.