Add a field to multiple views, is possible? - sql

I have to add a column, a field to multiple views in SQL Server. This is an example of a view that I'm using, where tbxxx stay for a table and vwxxx for a view:
ALTER VIEW [dbo].[vwFornitori_Search]
AS
SELECT IDitem,
IDana,
codice,
ragione_sociale,
c.valore AS colore
FROM tbAnagrafiche
LEFT JOIN tbColori c ON tbAnagrafiche.colore = c.IDcolore
WHERE IDitem = 'FOR'
AND ISNULL(eliminato, 0) = 0
AND ISNULL(obsoleto, 0) = 0
GO
I have to add to all my views another field, another column, that is always the principal table's primary key! The modified view will be:
ALTER VIEW [dbo].[vwFornitori_Search]
AS
SELECT IDitem,
IDana,
codice,
ragione_sociale,
c.valore AS colore,
IDana AS ID
FROM tbAnagrafiche
LEFT JOIN tbColori c ON tbAnagrafiche.colore = c.IDcolore
WHERE IDitem = 'FOR'
AND ISNULL(eliminato, 0) = 0
AND ISNULL(obsoleto, 0) = 0
GO
Usually the primary key has always the same name, like IDana. There's a way to do that with a single script to a list of views ?

You could do this by following these few steps:
1. Extract the SQL of the views' definitions:
SELECT CONCAT(m.definition, ';')
FROM sys.sql_modules m, sys.views v
WHERE m.object_id = v.object_id
AND v.name in ('myview1', 'myview2');
This outputs a list of SQL statements in the form:
CREATE VIEW myview1 (mycol1, mycol2) AS
SELECT ...;
CREATE VIEW myview1 (mycol1, mycol2, mycol3) AS
SELECT ...;
2. Manipulate the SQL
Copy/paste the above output in a text editor and perform an intelligent find/replace to insert the additional column in your select list.
The most simple find/replace would be:
Find: "FROM"
Replace: ", IDana AS ID FROM"
But this will not work if you have nested SELECT statements in your views. In that case you should use regular expressions, if your editor supports them, to make sure the replacement happens exactly where it should.
A regular expression like this would do it:
Find: "/(CREATE VIEW.*?SELECT.*?)FROM/gi"
Replace: "$1, IDana AS ID FROM"
Finally, replace all CREATE VIEW occurrences by ALTER VIEW.
3. Execute the final SQL
Copy/paste the manipulated SQL statements back into your database environment and execute them as a batch.

Related

How to Dynamically use a table from SSIS expression

I have Variable [User::Tablename1] String, I need an Expression that can evaluate at runtime, to check,
If Tablename1 is 'Customer'
select * from dbo.Customer where CustID = 1
Else If Tablename1 is any other tablename
"select * from dbo"**Tablename** where ProdID= 1
My concern is how to make the tablename dynamic and the filter column.
You should create two variables with these texts in the expression for your Select variables:
1: "select * from dbo."+[User::Tablename1]+ "where ProdID= 1"
2: "select * from dbo.Customer where CustID = 1"
Then you can use a sql command text for getting your table names and pass them as a input to a for each loop container to set it to your [User::Tablename1] variable.
In the for each you can use one Expression Task to compare 'Customer' with your [User::Tablename1] value.
At the end, by using the green arrow of the button of expression task, you can set the constraint with the result output. If the result is yes you can execute the Second select, else you execute the first select with any given table name.

I need to create a VIEW from an existing TABLE and MAP an additional COLUMN to that VIEW

I am fairly new to SQL. What I am trying to do is create a view from an existing table. I also need to add a new column to the view which maps to the values of an existing column in the table.
So within the view, if the value in a field for Col_1 = A, then the value in the corresponding row for New_Col = C etc
Does this even make sense? Would I use the CASE clause? Is mapping in this way even possible?
Thanks
The best way to do this is to create a mapping or lookup table
For example consider the following LOOKUP table.
COL_A NEW_VALUE
---- -----
A C
B D
Then you can have a query like this:
SELECT A.*, LOOK.NEW_VALUE
FROM TABLEA AS A
JOIN LOOKUP AS LOOK ON A.COL_A = LOOK.COL_A
This is what DimaSUN is doing in his query too -- but in his case he is creating the table dynamically in the body of the query.
Also note, I'm using a JOIN (which is an inner join) so only results in the lookup table will be returned. This could filter the results. A LEFT JOIN there would return all data from A but some of the new columns might be null.
Generally, a view is an instance of a table/a replica provided that there is no alteration to the original table. So, as per your query you can manipulate the data and columns in a view by using case.
Create View viewname as
Select *,
case when column=a.value then 'C'
....
ELSE
END
FROM ( Select * from table) a
If You have restricted list of replaced values You may hardcode that list in query
select T.*,map.New_Col
from ExistingTable T
left join (
values
('A','C')
,('B','D')
) map (Col_1,New_Col) on map.Col_1 = T.Col_1
In this sample You hardcode 'A' -> 'C' and 'B' -> 'D'
In general case You better may to use additional table ( see Hogan answer )

FoxPro: Append arbitrary number of views into a single view or table

I have several views which I need to combine into a single view or table. The views all have the same structure and are titled view_1, ..., view_x.
I've had the best luck with the following. I can get the total number of views in the database, so I have just used 12 here for simplicity. The code creates a new view called test and populates it with the contents of view_1 as expected. No errors are thrown when executed. In the status bar, I see that it has processed XXXX records. This corresponds to the last view (view_12). However, test only contains the contents of view_1.
create sql view test as;
select * ;
from view_1
for i = 2 to 12
insert into test ;
select * ;
from view_&i.
endfor
Am I missing something simple or is there a better way to do this?
You can't really treat views like tables unfortunately - they are just stored SQL statements. So to create a new view with the results of other views you essentially need to build a new SQL statement based on the SQL statements of the other views.
Note this assumes that the schema for each smaller view is the same, as you said :
Close All
Clear All
Clear
Open Database mydatabase Excl
lnViews = Adbobjects(laViews, "VIEW")
If Ascan(laViews, "vcombined") > 0
Delete View vcombined
Endif
lcSQL = ""
* -- You'll probably find out the view count and put it here.
For lnView = 1 to 3
lcView = "view_" + Transform(lnView)
lcSQL = lcSQL + Iif(lnView > 1, "union ", "") + DBGetProp(lcView, "View", "SQL")
Endfor
Create SQL View vcombined as &lcSQL
A VFP View is simply an SQL definition + some properties saved in the DBC. You could combine multiple views with same structure into a new view simply by using a "union ALL". However, it wouldn't be much realistic to have it as a single view as it wouldn't make sense to make it updatable.
Using those views to create the new one doesn't make much sense really. Instead you could directly use one view's SQL definition to create the final view. ie: If your view definitions are:
select CustomerId, CustomerName from Customers1
select CustomerId, CustomerName from Customers2
*...
select CustomerId, CustomerName from CustomersN
Then you could simply have your new definition as:
create sql view vMultiple as ;
select CustomerId, CustomerName from Customers1 ;
union all ;
select CustomerId, CustomerName from Customers2 ;
union all ;
* ... ;
select CustomerId, CustomerName from CustomersN
To add some indirect updatability to this, you might want to add a column for the source like:
create sql view vMultiple as ;
select 1 as Source, CustomerId, CustomerName from Customers1 ;
union all ;
select 2 as Source, CustomerId, CustomerName from Customers2 ;
union all ;
* ... ;
select N as Source, CustomerId, CustomerName from CustomersN
Since creating such a view doesn't make much sense, you might instead want to create it as a cursor when needed:
select 1 as Source, CustomerId, CustomerName from Customers1 ;
union all ;
select 2 as Source, CustomerId, CustomerName from Customers2 ;
union all ;
* ... ;
select N as Source, CustomerId, CustomerName from CustomersN ;
into cursor crsMultiple ;
nofilter && or readwrite if it needs any updating
Remember, both cursors and views (also a cursor) do not have persistent indexes and view cursors are buffered. You would create your index(es) as needed.
Think twice, why you need a view for this (or any view).

Is putting a OR condition when Selecting/Displaying columns valid?

new to SQL, I was wondering if its valid to put a "or" condition when choosing columns (SELECT)?
Example:
SELECT (Column1 OR Column2)
My Aim:
I'm currently creating a view that will display all claim types basic information that I will use for queries. Obviously, they are in different tables, so I was hoping to merge them into one view for easy access. The problem is when created the view puts the columns with OR statement to either a 1 or 0, when it should be a VARCHAR (string).
Full SQL Query:
CREATE VIEW ViewAllClaims AS
SELECT Claim.ClaimID, Claim.CreatedDate, (ReturnClaim.ClaimStatus or RepairClaim.ClaimStatus) as 'ClaimStatus', (SupplierName or FirstName) as 'Name'
FROM Claim, ReturnClaim, RepairClaim, Supplier, Product, ReturnClaimProduct, Customer
WHERE ( Claim.ClaimID = ReturnClaim.ClaimID
AND ReturnClaim.ClaimID = ReturnClaimProduct.ClaimID
AND ReturnClaimProduct.Keycode = Product.Keycode
AND Product.SupplierID = Supplier.SupplierID)
or
(Claim.ClaimID = RepairClaim.ClaimID
AND RepairClaim.CustomerID = Customer.CustomerID);
Screenshot of the result:
You can use CASE:
SELECT (
CASE
WHEN ReturnClaim.ClaimStatus IS NULL THEN RepairClaim.ClaimStatus
ELSE ReturnClaim.ClaimStatus
END
) AS 'ClaimStatus'
FROM ...

Why can't I query individual columns in a SQL view?

I've used a script to create a view that has the table name for every table in a database, along with the number of rows of data in the respective table. Everything works fine with SELECT *. However, I'd like to query only certain rows, but I can't seem to do that.
The view was created with the following script (credit to DatabaseZone.com for the script):
CREATE VIEW RowCount_AllTables
AS
SELECT DISTINCT
sys.schemas.name, sys.tables.name AS tableName,
sys.dm_db_partition_stats.row_count AS 'RowCount'
FROM
sys.tables
INNER JOIN
sys.dm_db_partition_stats ON sys.tables.object_id = sys.dm_db_partition_stats.object_id
INNER JOIN
sys.schemas ON sys.tables.schema_id = sys.schemas.schema_id
WHERE
(sys.tables.is_ms_shipped = 0)
When I run Select * against the resulting view, I get results such as:
name tableName RowCount
dbo Table1 2
dbo Table2 1230
dbo Table3 0
If I query just the tableName column, that works fine and returns the table names. However, if I try to query the RowCount column as well, I get the error message Incorrect syntax near the keyword 'RowCount. This happens regardless of whether I qualify the database -- it seems to not recognize RowCount as a valid column that I can call in a query. So this script fails:
SELECT RowCount
FROM RowCount_AllTables;
But this one works:
SELECT tableName
FROM RowCount_AllTables;
What's going on? I'd like to be able to alias the column names in the view in my query but I can't do that so long as I can't reference the RowCount column.
(FYI running this in SQL Server 2014)
Rowcount is a reserved word, you can select reserved words using [] as:
[Rowcount]
Thanks to #sgeddes for pointing the way. Dropped the view, changed the script for creating it to use another name for the row count column, and it now works as expected. The issue was a conflict with Rowcount being a reserved word.
Changed the create table script on this line:
SELECT distinct sys.schemas.name, sys.tables.name AS tableName,
sys.dm_db_partition_stats.row_count AS 'RowCount'
to:
SELECT distinct sys.schemas.name, sys.tables.name AS tableName,
sys.dm_db_partition_stats.row_count AS 'Row_Count'
...at which point I can now reference the Row_Count column as desired.