SQL Server method for user record selection - sql-server

I am migrating a large Access application to SQL Server.
One technique that I use in Access is to use a selection table in the frontend joined to a shared backend table to allow the user to select individual records. Once the user has specified the selection, I then use the selection as a criteria to update, export or report on the selected records.
The selection table simply consists of a foreign key field and a boolean field used to display a checkbox for the record selection.
Here is an example showing the equivalent of what I do in Access:
CREATE TABLE tblJob (
JobNumber int NOT NULL,
JobName nchar(255) NULL
)
ALTER TABLE tblJob ADD CONSTRAINT PrimaryKey PRIMARY KEY CLUSTERED
(
JobNumber ASC
)
GO
INSERT INTO tblJob (JobNumber, JobName) VALUES (1, 'Job 1')
INSERT INTO tblJob (JobNumber, JobName) VALUES (2, 'Job 2')
INSERT INTO tblJob (JobNumber, JobName) VALUES (3, 'Job 3')
GO
CREATE TABLE tblSelect (
SelectID int NOT NULL,
Selected int NOT NULL
)
--CREATE UNIQUE NONCLUSTERED INDEX PrimaryKey ON tblSelect (
-- SelectID ASC
--)
ALTER TABLE tblSelect ADD DEFAULT (0) FOR Selected
GO
-- Create a view joining the selection table tblSelect to the data table tblJob
CREATE OR ALTER VIEW vwJobSelected
AS
SELECT
JobNumber,
JobName,
Selected
FROM tblJob
LEFT OUTER JOIN tblSelect ON tblJob.JobNumber = tblSelect.SelectID
GO
-- The application initialises tblSelect with the Job keys
DELETE FROM tblSelect
GO
INSERT INTO tblSelect(SelectID, Selected)
SELECT JobNumber, 0 FROM tblJob
GO
-- The user selects the second record via an editing form in the application
UPDATE vwJobSelected
SET Selected=1
WHERE JobNumber = 2
GO
-- Show the selected record(s)
SELECT *
FROM vwJobSelected
WHERE Selected=1
GO
This works well in Access but will not work in SQL Server for the following reasons:
The selection tblSelect is in the frontend database and therefore is unique to the user/workstation/running instance of the application. However with the migrated database this would create a “heterongenous join” which would join the tables on the client instead of the server and therefore drag the whole data table tblJob across the network.
Access allows the query with the left outer join to be modified seamlessly. However SQL Server will not let you delete records since there are multiple base tables. This would require an INSTEAD OF trigger on the view.
So my question is: What is the recommend method for performing this user selection process in SQL Server?
I have considered:
a) Adding columns for UserName (= SUSER_NAME()) and Workstation (=HOST_NAME()) to tblSelect so that there are user/workstation specific selections available. However I think Access will require a unique index on SelectedID to keep the query updatable and this presents problems.
b) Temporary tables. However I get the impression that these only persist for the duration of a connection to the server and the Access application will surely disconnect and reconnect to the server within the duration of running a session.
c) Asking the good folk at Stack Overflow for advice! :-)
Kind regards
Neil Sargent

Related

Which are the simplest way to do cross database references in pgAdmin?

I want to do horizontal fragmentation on a table say table employee(attributes) which is in 'Employee' database on 'server1' and such fragments are need to store in table on other databases on same server. For doing this I am currently using rules so that changes can be replicated. For example if some insert happens on one of the fragment then those inserted values should also must get stored on main table. So I need to write cross database referencing queries for this. Can anyone tell me how to write such queries in pgAdmin , specially for creating rules for ex:
CREATE RULE employee1 AS
ON INSERT TO employee WHERE
( dno BETWEEN 1 AND 10 )
DO INSTEAD
INSERT INTO employee1 VALUES ( NEW.eno, NEW.ename, NEW.title, NEW.dno );
where table employee and employee1 resides on different database but on same server.

Migrate tables from MS Access to MS SQL Server [duplicate]

This question already has answers here:
Migration Access to SQL server 2012
(4 answers)
Closed 8 years ago.
I'm moving a database from MS Access to MS SQL Server 2012. My question involves a data issue we need to resolve for the SQL Server database. We have a main MS Access table that generates an integer key then used in several other tables. In Access, the column autoincrements when a new record is created. The issue we're having is that there are gaps in the Access tables columny where records were (unwisely) deleted. It seems that the solution for the SQL Server version of he table is to migrate the table with that column set as PRIMARY and UNIQUE, without using the IDENTITY value. That means we would no longer get an autoincremented number. We'd have to write some code to create that numbering using a SELECT with MAX(). Is there a better way to resolve this issue?
You have TableA that currently maintains the Primary Key that is used is related tables. You want TableB to now control the creation of this Primary Key. I don't see why you can't continue using an auto-incrementing primary key on TableB to manage the creation of the Primary Key. It doesn't matter that previous values have gaps. SQL Server has a way around that.
You can't convert an exiting column in a table to IDENTITY, but you can create a table in SQL Server with an IDENTITY column, turn the IDENTITY function off, populate it with your own values (gaps and all), and then turn the IDENTITY function back on.
From the documentation on IDENTITY_INSERT:
-- Create products table.
CREATE TABLE products (id int IDENTITY PRIMARY KEY, product varchar(40))
GO
-- Inserting values into products table.
INSERT INTO products (product) VALUES ('screwdriver')
INSERT INTO products (product) VALUES ('hammer')
INSERT INTO products (product) VALUES ('saw')
INSERT INTO products (product) VALUES ('shovel')
GO
-- Create a gap in the identity values.
DELETE products
WHERE product = 'saw'
GO
SELECT *
FROM products
GO
-- Attempt to insert an explicit ID value of 3;
-- should return a warning.
INSERT INTO products (id, product) VALUES(3, 'garden shovel')
GO
-- SET IDENTITY_INSERT to ON.
SET IDENTITY_INSERT products ON
GO
-- Attempt to insert an explicit ID value of 3
INSERT INTO products (id, product) VALUES(3, 'garden shovel').
GO
-- SET IDENTITY_INSERT to OFF.
SET IDENTITY_INSERT products OFF
GO
SELECT *
FROM products
Using this technique, you can convert the Access version of TableB to temp_TableB in SQL Server, where there is no identity column. Then create a real TableB in SQL Server with an IDENTITY column.
Then you could
SET IDENTITY_INSERT TableB ON
INSERT INTO TableB ( {columnlist} )
SELECT * from temp_TableB
SET IDENTITY_INSERT TableB OFF
Now you have TableB populated correctly and ready to create the next auto-incremented IDENTITY value.

Relations between Table and View using Microsoft SQL

Is there a natural option to establish a relationship between table and view or i should use trigger as a workaround to check that the data consistency?
I have a lookup view (for some reason i need it to be view and not a table).
I want to insert records to a different table. one of the values of the record i want to insert MUST be one of the ids from the lookup view.
For example:
ViewCities (CityId, CityName) -- This is the lookup View. the table behind the view located on a different database.
now i want to insert new row to tblUsers. one of the row columns is CityId. I want that not one will be able to insert a row to tblUsers that includes cityid that not exists on ViewCities.
You have two options that I am aware of to maintain referential integrity. You cannot use a foreign key constraint because you said that the tables are in two separate databases. The options are:
1. Use triggers, as you had mentioned.
2. Use a check constraint which references a user defined function which does the check.
For example:
Let's say I have a database named test, and another database is the Northwind database. In my test database I want to create a table which records names of users. The check I want to enforce is that the user name must be one of the LastName's of a user in the Northwind database. I first create a UDF like so:
create function chk_name (#name varchar(50))
returns bit
as
begin
declare #name_found bit=0
if exists(select * from Northwind..Employees where LastName=#name)
begin
set #name_found=1
end
return #name_found
end
Then, I create the table with a check constraint like so:
create table tst
(name varchar(50) check ( dbo.chk_name(name)=1 )
)
Now, if you try to insert a row into the tst table, it must be one of the Last Names of the Employees table in the Northwind database.

update null primary key in a trigger using SQL Server

I'm migrating our system from Oracle to SQL SERVER. In Oracle we have insert triggers that are resposnible for setting primary key if not set. Below you will find code from PL/SQL.
create or replace trigger trigg1
before insert on table1
for each row
when (new.ID_T1 is null) -- if primary key is null
begin
select OUR_SEQ.nextval into :new.ID_T1 from dual;
end trigg1;
Now I have to do something similar in T-SQL. I found the solution, but unfortunatelly I have to list all the columns for the table trigger is created. This is something I want to avoid (model for the system is still very dynamic).
Is it possible to implement such trigger without listing all the columns in trigger?
Marcin

How do I get MS LightSwitch to recognize my View?

I've created a View from a table in another database. I have dbo rights to the databases so viewing and updating is not a problem. This particular View did not have an "id" column. So I added one to the View by using ROW_NUMBER. Now I had a problem with a table, in the same database, not showing up in LightSwitch but that was solved by changing the id column to be NOT NULL. I haven't done any real manipulation in LightSwitch. I'm still in the Import Your Data Source stage (ie. very beginning).
This View, in LightSwitch, is going to be read-only. No updating or deleting. From what I've read, LightSwitch needs a way to determine the PK of a Table or View. It either reads it from the schema (column set as a PK) or finds a column set as NOT NULL and uses that as the PK. Well I can't seem to do either of those things in SQL Server or LightSwitch, so I am stuck as to how to get LightSwitch to "see" my View.
for lightswitch to see your view you must have a primary key on a column of the table your are selecting from.
Example:
create table tbl_test
(
id int identity primary key not null,
value varchar(50)
)
create view vw_test
as
select *
from tbl_test
note:sometimes when you edit the primary key column in the view select statement it may cause lightswitch to not see it
Example:
create view vw_test
select cast(id as varchar(50) id,...
lightswitch would not see the table
Hope this was helpful! :)
What I do in this case is create a view with an ID column equal to the row number. Ensure the column you're basing the ID on is not null using the isnull() or coalesce() functions.
Example:
create view as
select distinct ID = row_number() over (order by isnull(Name,'')),
Name = isnull(Name,'')
from My_Table

Resources