Refresh View after table drop - sql-server

I have the following tables:
Series One Tables:
create table tbl1
(
id int,
name varchar(100)
);
insert into tbl1 values(1,'tbl1');
create table tbl2
(
id int,
name varchar(100)
);
insert into tbl2 values(1,'tbl2');
create table tbl3
(
id int,
name varchar(100)
);
insert into tbl3 values(1,'tbl3');
create table tbl4
(
id int,
name varchar(100)
);
insert into tbl4 values(1,'tbl4');
Series Double Tables:
create table tbl11
(
id int,
name varchar(100)
);
insert into tbl11 values(1,'tbl11');
create table tbl22
(
id int,
name varchar(100)
);
insert into tbl22 values(1,'tb22');
create table tbl33
(
id int,
name varchar(100)
);
insert into tbl33 values(1,'tbl33');
create table tbl44
(
id int,
name varchar(100)
);
insert into tbl44 values(1,'tbl44');
Now I want to create VIEW of each series tables:
Series One View:
create view View_tbl_one_series as
select * from tbl1
union all
select * from tbl2
union all
select * from tbl3
union all
select * from tbl4
Series Double View:
create view View_tbl_double_series as
select * from tbl11
union all
select * from tbl22
union all
select * from tbl33
union all
select * from tbl44
After that I DROP TABLE tbl1 for some reason and creating another VIEW which contains the definition of two series views.
VIEW ALL:
create view All_VIEW AS
select * from View_tbl_one_series
union all
select * from View_tbl_double_series
Getting an error:
Msg 208, Level 16, State 1, Procedure View_tbl_one_series, Line 2
Invalid object name 'tbl1'.
Try:
exec sp_refreshview View_tbl_one_series
but still getting same error.
Note: I have many tables and views in the database system, and creating view all is the last procedure, and between that have to drop some tables for some reason.

A non materialized view in SQL Server can be thought of as just a thin wrapper on top of the underlying tables which appear in that view. If you drop one or more of the tables involved in the view, it won't work, because the table can no longer be queried. There are a number of workarounds here, one of which would be to just create an indexed (materialized) view:
CREATE VIEW View_tbl_one_series
WITH SCHEMABINDING
AS
SELECT * from tbl1
UNION ALL
SELECT * from tbl2
UNION ALL
SELECT * from tbl3
UNION ALL
SELECT * from tbl4
GO
CREATE UNIQUE CLUSTERED INDEX idx ON View_tbl_one_series (id);
Other options would include using a temporary table for the same purpose, or maybe even a bona fide regular table.
Note that in general doing SELECT * in a union query is not ideal, because it leaves open the possibility that the columns/column types may not line up properly between the two tables involved in the union.

Related

Join a table whose name is stored in the first table

I have a first table [TABLE1] with columns [ID], [Description], [DetailTable]. I want to join [TABLE1] with the [DetailTable]. The name of [DetailTable] is stored in [TABLE1] column.
"SELECT * FROM TABLE1 CROSS JOIN ?????"
Any suggestions?
So... if you cheat and SELECT * from the detailtab, you could do something a bit like this, with dynamic SQL:
-- For the example, choose either 1 or 2 to see the #foo table or the #bar table
DECLARE #Id INT = 1
-- EXAMPLE SCENARIO SETUP --
CREATE TABLE #ListOfTables
( ID INT IDENTITY(1,1) NOT NULL
,[Description] NVARCHAR(255) NOT NULL
,[DetailTable] NVARCHAR(255) NOT NULL);
CREATE TABLE #foo
(Foothing VARCHAR(20));
CREATE TABLE #bar
(Barthing VARCHAR(20));
-- TEST VALUES --
INSERT #ListOfTables VALUES ('foo','#foo'),('bar','#bar');
INSERT #foo VALUES ('A foothing Foothing');
INSERT #bar VALUES ('A barthing Barthing');
-- THE SCRIPT --
DECLARE #SQL NVARCHAR(MAX) = '';
SELECT #SQL =
' SELECT Tab.Id, Tab.[Description], Tab2.*
FROM #ListOfTables AS Tab
CROSS JOIN ' + T.DetailTable + ' AS Tab2
WHERE Tab.Id = ' + CONVERT(VARCHAR(10),#Id)
FROM #ListOfTables T
WHERE T.Id = #Id;
PRINT #SQL
EXEC sp_executesql #SQL;
-- CLEAN UP --
DROP TABLE #ListOfTables;
DROP TABLE #bar;
DROP TABLE #foo;
However, I have to agree with the comments that this is a pretty nasty way to do things. If you want to choose particular columns and the columns are different for each detail table, then things will start to get really unpleasant... Does this give you something you can start with?
Remember, the best solution will almost certainly involve redesigning things so you don't have to jump through these hoops!
All of the detail tables must have identical schema.
Create a view that unions all the tables
CREATE VIEW vAllDetails AS
SELECT 'DETAIL1' table_name, * from DETAIL1
UNION ALL
SELECT 'DETAIL2' table_name, * from DETAIL2
UNION ALL
SELECT 'DETAIL3' table_name, * from DETAIL3
When you join against this view, SQL Server can generate a plan that uses a "startup predicate expression". For example, a plan like this: sample plan. At first glance, it looks like SQL is going to scan all of the detail tables, but it won't. The left most filters include a "startup predicate", so for each row we read from table1, only if TableName matches will that branch be executed.

Checking whether value exists in results of a stored procedure

I have a stored procedure which returns a list of IDs for a particular set of generators I want to be able to then use the results of this stored procedure as part of another query.
Can I write a query like:
select * from table where id in (exec dbo.storedprocedurename)
Using table variable and JOIN you can achieve this. Store the procedure result into the table.
DECLARE #ProcOutput TABLE (Id INT);
INSERT INTO #ProcOutput (Id)
EXEC [dbo].[storedprocedurename]
SELECT T.*
FROM Table T
JOIN #ProcOutput O ON O.Id = T.Id
If the procedure returns multiple entries, according to the output you can re-design the table's schema.
If your output of procedure is 2 columns then you may try this:
INSERT INTO MyTable
(
Col1,
Col2
)
EXEC [dbo].[storedprocedurename]
GO
SELECT * FROM TABLE WHERE ID IN (SELECT Col1 from Mytable)

SQL Server view metadata information

I have a table as below:
create table employee_details
(
id int,
name varchar(10)
)
And this is a view based on employee_details:
create view vw_empl_details
as
select id as emp_id, name as emp_name
from employee_details
I want to know which system table keeps track of column wise information for above condition..
id-> emp_id
name-> emp_name
we have below 2 tables to keep track of tables but not sure columnwise information is available in SQL Server
select * from [INFORMATION_SCHEMA].[VIEW_COLUMN_USAGE]
select * from [INFORMATION_SCHEMA].VIEW_TABLE_USAGE
I guess you want (sys.sql_modules.definition):
SELECT *
FROM sys.sql_modules
WHERE OBJECT_ID = OBJECT_ID('vw_empl_details');
Rextester.com
Mapping only when there is simple aliasing:
SELECT column_ordinal, name, source_table, source_column
FROM sys.dm_exec_describe_first_result_set
('SELECT * FROM vw_empl_details', NULL, 1);
Output:
Rextester Demo2

How to save select query results within temporary table?

I need to save select query output into temporary table. Then I need to make another select query against this temporary table. Does anybody know how to do it?
I need to make this on SQL Server.
select *
into #TempTable
from SomeTale
select *
from #TempTable
You can also do the following:
CREATE TABLE #TEMPTABLE
(
Column1 type1,
Column2 type2,
Column3 type3
)
INSERT INTO #TEMPTABLE
SELECT ...
SELECT *
FROM #TEMPTABLE ...
DROP TABLE #TEMPTABLE
In Sqlite:
CREATE TABLE T AS
SELECT * FROM ...;
-- Use temporary table `T`
DROP TABLE T;

SELECT INTO a table variable in T-SQL

Got a complex SELECT query, from which I would like to insert all rows into a table variable, but T-SQL doesn't allow it.
Along the same lines, you cannot use a table variable with SELECT INTO or INSERT EXEC queries.
http://odetocode.com/Articles/365.aspx
Short example:
declare #userData TABLE(
name varchar(30) NOT NULL,
oldlocation varchar(30) NOT NULL
)
SELECT name, location
INTO #userData
FROM myTable
INNER JOIN otherTable ON ...
WHERE age > 30
The data in the table variable would be later used to insert/update it back into different tables (mostly copy of the same data with minor updates). The goal of this would be to simply make the script a bit more readable and more easily customisable than doing the SELECT INTO directly into the right tables.
Performance is not an issue, as the rowcount is fairly small and it's only manually run when needed.
...or just tell me if I'm doing it all wrong.
Try something like this:
DECLARE #userData TABLE(
name varchar(30) NOT NULL,
oldlocation varchar(30) NOT NULL
);
INSERT INTO #userData (name, oldlocation)
SELECT name, location FROM myTable
INNER JOIN otherTable ON ...
WHERE age > 30;
The purpose of SELECT INTO is (per the docs, my emphasis)
To create a new table from values in another table
But you already have a target table! So what you want is
The INSERT statement adds one or more new rows to a table
You can specify the data values in the
following ways:
...
By using a SELECT subquery to specify
the data values for one or more rows,
such as:
INSERT INTO MyTable
(PriKey, Description)
SELECT ForeignKey, Description
FROM SomeView
And in this syntax, it's allowed for MyTable to be a table variable.
You can also use common table expressions to store temporary datasets. They are more elegant and adhoc friendly:
WITH userData (name, oldlocation)
AS
(
SELECT name, location
FROM myTable INNER JOIN
otherTable ON ...
WHERE age>30
)
SELECT *
FROM userData -- you can also reuse the recordset in subqueries and joins
You could try using temporary tables...if you are not doing it from an application. (It may be ok to run this manually)
SELECT name, location INTO #userData FROM myTable
INNER JOIN otherTable ON ...
WHERE age>30
You skip the effort to declare the table that way...
Helps for adhoc queries...This creates a local temp table which wont be visible to other sessions unless you are in the same session. Maybe a problem if you are running query from an app.
if you require it to running on an app, use variables declared this way :
DECLARE #userData TABLE(
name varchar(30) NOT NULL,
oldlocation varchar(30) NOT NULL
);
INSERT INTO #userData
SELECT name, location FROM myTable
INNER JOIN otherTable ON ...
WHERE age > 30;
Edit: as many of you mentioned updated visibility to session from connection. Creating temp tables is not an option for web applications, as sessions can be reused, stick to temp variables in those cases
Try to use INSERT instead of SELECT INTO:
DECLARE #UserData TABLE(
name varchar(30) NOT NULL,
oldlocation varchar(30) NOT NULL
)
INSERT #UserData
SELECT name, oldlocation
First create a temp table :
Step 1:
create table #tblOm_Temp (
Name varchar(100),
Age Int ,
RollNumber bigint
)
**Step 2: ** Insert Some value in Temp table .
insert into #tblom_temp values('Om Pandey',102,1347)
Step 3: Declare a table Variable to hold temp table data.
declare #tblOm_Variable table(
Name Varchar(100),
Age int,
RollNumber bigint
)
Step 4: select value from temp table and insert into table variable.
insert into #tblOm_Variable select * from #tblom_temp
Finally value is inserted from a temp table to Table variable
Step 5: Can Check inserted value in table variable.
select * from #tblOm_Variable
OK, Now with enough effort i am able to insert into #table using the below :
INSERT #TempWithheldTable SELECT
a.SuspendedReason,
a.SuspendedNotes,
a.SuspendedBy ,
a.ReasonCode FROM OPENROWSET( BULK 'C:\DataBases\WithHeld.csv', FORMATFILE =
N'C:\DataBases\Format.txt',
ERRORFILE=N'C:\Temp\MovieLensRatings.txt'
) AS a;
The main thing here is selecting columns to insert .
One reason to use SELECT INTO is that it allows you to use IDENTITY:
SELECT IDENTITY(INT,1,1) AS Id, name
INTO #MyTable
FROM (SELECT name FROM AnotherTable) AS t
This would not work with a table variable, which is too bad...

Resources