Sql how to switch tables - sql-server

I have two tables one of them have historical(cdr_hist) data other table have data from today(cdr_stage). My script must run every 30 minutes and calculate data from last 4 hours but every night at 12 all data move at cdr_hist.
The question is how I can switch and take data from history table when script run at 12:00 because cdr_stage is empty...
I tried this:
IF OBJECT_ID ('[**CDR_Stage**]') IS NOT NULL
BEGIN
Select.....
From **CDR_Stage**
END
ELSE
Select.....
From **CDR_Hist**
END
But its not work correctly...
Any ideas??

No need for IFs , that can be done with pure sql using UNION and NOT EXISTS() :
SELECT * FROM CDR_Stage
UNION ALL
SELECT * FROM CDR_Hist
WHERE NOT EXISTS(SELECT 1 FROM CDR_Stage) -- Second select will return data only if first one won't .

You need to check the record existence instead of table existence
IF EXISTS (SELECT 1
FROM CDR_Stage)
SELECT *
FROM CDR_Stage
ELSE
SELECT *
FROM CDR_Hist
Or Dynamic Sql
DECLARE #sql VARCHAR(4000)
SET #sql = 'select * from '
+ CASE
WHEN EXISTS (SELECT 1
FROM CDR_Stage) THEN 'CDR_Stage'
ELSE 'CDR_Hist'
END
EXEC (#sql)

Related

Update table from 2 Selects from a different database with thousands of rows SQL

I have 2 Openquerys that are just simple selects from 2 tables. My objective is to populate a single table with data from those 2 queries that basically return the same thing but with different names.
Example
1st Warehouse 1
Select * From OpenQuery ('SELECT * FROM Warehouse1')
2nd Warehouse 2
Select * From OpenQuery ('SELECT * FROM Warehouse2')
There are thousands of rows that i need to update my SQL table. Problem is, this is very expensive if i use UNION, and my question is how can achieve this for best performance possible? Also this is data from an external database so i really can't change the queries
I have to update my main table with these queries only when user access the list that shows the data
EDIT.
I wasn't very clear but both tables return same type of column
| ID | Warehouse | Ticket | Item | Qty
One belongs to Warehouse 1, the other to Warehouse 2, both have different amount of rows.
You can use inner join with update for this you need to make table alias as shown below
UPDATE A
SET A.<ColName> = B.<ColName>
from Warehouse1 A
INNER JOIN Warehouse2 B
ON A.<Id> = B.<Id>
--where if required
But why you need to UNION?
You can simply insert 2 times under a transaction.
BEGIN TRY
BEGIN TRAN T1
INSERT into mytable
--select from openquery table 1
INSERT into mytable
--select from openquery table 2
COMMIT TRAN T1
END TRY
BEGIN CATCH
---handle error
ROLLBACK TRAN T1
END CATCH
For anyone with the same problem as me. Here is the solution i came up with that suits my problem better.
I save the open query on a view since I don't need to change anything or insert in my database at all
/*************************** Views ********************************/
GO
IF OBJECT_ID('viewx_POE', 'v') IS NOT NULL
DROP VIEW viewx_POE
GO
CREATE VIEW viewx_POE AS
SELECT ET0104 AS Armazem,
ET0109 AS Localizacao,
ET0102 AS Etiqueta,
ET0101 AS Artigo,
ET0103 AS Quantidade
FROM OpenQuery(MACPAC, 'SELECT FET001.ET0104, FET001.ET0109, FET001.ET0102, FET001.ET0101, FET001.ET0103
FROM AUTO.D805DATPOR.FET001 FET001
WHERE (FET001.ET0104=''POE'') AND (FET001.ET0105=''DIS'')');
/**************************************************************************/
GO
IF OBJECT_ID('viewx_CORRICA', 'v') IS NOT NULL
DROP VIEW viewx_CORRICA
GO
CREATE VIEW viewx_CORRICA AS
SELECT GHZORI AS Armazem,
GHNEMP AS Localizacao,
LBLBNB AS Etiqueta,
GHLIB5 AS Artigo,
LBQTYD AS Quantidade
FROM OpenQuery(MACPAC, 'SELECT GA160H.LBLBNB, GA160H.GHLIB5, GA160H.GHZORI, GA160H.GHNEMP, GA160M.LBQTYD
FROM D805DATPOR.GA160H GA160H, D805DATPOR.GA160M GA160M
WHERE GA160M.LBLBNB = GA160H.LBLBNB AND (GA160H.GHZORI=''CORRICA'' AND GA160H.GHCSTA=''DIS'')');
And then when needed I select the view depending on the user rank and return whatever i need from it
GO
IF OBJECT_ID('dbo.spx_SELECT_RandomLocalizacoes') IS NOT NULL
DROP PROCEDURE spx_SELECT_RandomLocalizacoes
GO
CREATE PROCEDURE spx_SELECT_RandomLocalizacoes
#LocalizacoesMax int,
#Armazem int
AS
BEGIN
SET NOCOUNT ON
DECLARE #Output int
IF ( #Armazem = 'POE' )
BEGIN
SELECT TOP(10) xa.IdArmazem, vpoe.Localizacao, vpoe.Etiqueta, vpoe.Artigo, vpoe.Quantidade
FROM viewx_POE vpoe
INNER JOIN xArmazem xa
ON vpoe.Armazem = xa.Armazem
ORDER BY NEWID()
END
ELSE IF ( #Armazem = 'CORRICA' )
BEGIN
SELECT TOP(#LocalizacoesMax) * FROM viewx_CORRICA ORDER BY NEWID()
END
END

How to ensure specific WHERE condition evaluates first on view

Consider the following view:
create view x as
select 1 as [source],* from some_table
union all
select 2,* from some_other_table
When I run
select * from x where source=1
can I be sure that the select 2.... query is not even executed?
The reason is that in my case, that one is an openquery with sluggish speed, which I want to avoid.
You can do stuff like this, but i dont know if that meets your other requirements you might have - Otherwise you can create 2 views.
CREATE proc dbo.usp_selectspecificquery
#source int
AS
BEGIN
IF(#source = 1)
BEGIN
Select 1 as source, * from some_table
END
ELSE
Select 1 as source,* from some_table
union all
select 2 as source,* from some_other_table
END
exec dbo.usp_selectspecificquery 1

Stored procedure with conditional Where clause in SQL Server

I am creating a SQL Server stored procedure. It's a simple SELECT query that I am building. One of the parameters is to look for a flag parameter. If that parameter is left blank, then the SELECT should default to NOT having the WHERE clause at all.
CREATE PROCEDURE sprocA
#flagInd int
AS
BEGIN
SELECT intID, strQuestion, strAnswer, intCategory, intOrder
FROM tblA
-- Right here is where I am looking for the logic of the #flagInd to be evaluated.....
-- if #flagInd = 1 then 'WHERE flgInd=1'
-- else if #flagInd=0 then 'WHERE flgInd=0'
-- else if #flagInd IS NULL then ''
It's just a simple query and a simple thought I had, not sure if it can be done without nesting and rewriting the whole SELECT statement as part of of the IF statement.
This can be done like:
SELECT intID, strQuestion, strAnswer, intCategory, intOrder
FROM tblA
WHERE flgInd = #flgInd OR #flgInd IS NULL;
You can also use a CASE expression:
SELECT intID, strQuestion, strAnswer, intCategory, intOrder
FROM tblA
WHERE CASE
WHEN flgInd = #flgInd THEN 1
WHEN #flgInd IS NULL THEN 1
ELSE 0
END = 1;
There appears to just be a one to one mapping (from the parameter to the column) so why not use a simple where clause?
CREATE PROCEDURE sprocA
#flagInd int
AS
BEGIN
SELECT intID, strQuestion, strAnswer, intCategory, intOrder
FROM tblA WHERE flgInd = #flagInd;

SQL SERVER Select multiple fields from If Exists

I have to do an SQL Server Statement that have to return an empty row when is null, and data otherwhise.
I am trying to do a Select from (if exisits) but have an error on parent table.
I Simplify it. But the meaning, is to retrieve a couple of fields when condition is null and other fields when it is not null.
It Works fine when I do not clouse it in another select.... I need to retrieve it as a table to do an inner Join with other clouse.
How can i resolved it?
Here is my code..
select * from
(
if exists(select isnull(SECTOR_ID_DESTINO_BAD,-1)
from workflow_Compras_detalle w
where w.id=2)
begin
select null as Sector,null as sector_id_origen
end
else
begin
select top 1 isnull(ws.sector,'') sector, wd.sector_id_origen
from workflow_Compras_detalle wd
where orden < 10
end
)Table
you should try to insert the data into a temporary table or Table Variable, then get the data from that table, here is an example with a Table Variable, if you need something more persistent you may use a #Temp Table, i recommend you take a look to this: difference between var table and #Temp Table
DECLARE #VAR_TABLE AS TABLE(
Sector varchar(25),
sector_id_origen int
)
if exists(select isnull(SECTOR_ID_DESTINO_BAD,-1)
from workflow_Compras_detalle w
where w.id=2)
begin
INSERT INTO #VAR_TABLE
Select null as Sector,null as sector_id_origen
End
Else
begin
INSERT INTO #VAR_TABLE
select top 1 isnull(ws.sector,'') sector, wd.sector_id_origen
from workflow_Compras_detalle wd
where orden < 10
End
SELECT * FROM #VAR_TABLE

How to view ALL COLUMNS (same column names from all table) from all tables starting with Letter A?

Is this possible? I am using ORACLE 10g.
For example: I have 50 tables name A01, A02, A03, A04.........A50.
And all these tables have the "SAME COLUMN NAME"
For example: name, age, location
(Note: The Column Names are the same but not the value in the columns).
In the END... I want to view all data from column: name, age, location FROM ALL tables starting with letter A.
(Note 2: All tables starting with letter A are NOT STATIC, they are dynamic meaning different changes could occur. Example: A01 to A10 could be deleted and A99 Could be added).
Sorry for not clarifying.
DECLARE
TYPE CurTyp IS REF CURSOR;
v_cursor CurTyp;
v_record A01%ROWTYPE;
v_stmt_str VARCHAR2(4000);
BEGIN
for rec in (
select table_name
from user_tables
where table_name like 'A%'
) loop
if v_stmt_str is not null then
v_stmt_str := v_stmt_str || ' union all ';
end if;
v_stmt_str := v_stmt_str || 'SELECT * FROM ' || rec.table_name;
end loop;
OPEN v_cursor FOR v_stmt_str;
LOOP
FETCH v_cursor INTO v_record;
EXIT WHEN v_cursor%NOTFOUND;
-- Read values v_record.name, v_record.age, v_record.location
-- Do something with them
END LOOP;
CLOSE v_cursor;
END;
As per my understanding if you want to view all column names of tables starting with A then try below
select column_name,table_name from user_tab_cols where table_name like 'A%';
If your requirement is something else then specify it clearly.
If understand you correctly and the number of tables is constant then you can create a VIEW once
CREATE VIEW vw_all
AS
SELECT name, age, location FROM A01
UNION ALL
SELECT name, age, location FROM A01
UNION ALL
...
SELECT name, age, location FROM A50
UNION ALL
And then use it
SELECT *
FROM vw_all
WHERE age < 35
ORDER BY name
This returns you all tables you need:
select table_name
from user_tables
where table_name like 'A__';
From this, you can build a dynamic sql statement as:
select listagg('select * from '||table_name,' union all ') within group(order by table_name)
from user_tables
where table_name like 'A__'
This returns actually an SQL statement which contains all tables and the unions:
select * from A01 union all select * from A02 union all select * from A03
And finally execute this via native dynamic sql. You can do that in PL/SQL, so you need a function:
create function getA
query varchar2(32000);
begin
select listagg('select * from '||table_name,' union all ') within group(order by table_name)
into query
from user_tables
where table_name like 'A__';
open res for query;
return res;
end;
Note that what you're doing manually is basically called partitioning, and Oracle has a super-great support already available for that out of the box. I.e. you can have something which looks like a super-huge table, but technically it is stored as a set of smaller tables (and smaller indexes), splitted by a partitioning criteria. For example, if you have millions of payment records, you may partition it by year, this way one physical table contains only a reasonable set of data. Still, you can freely select in this, and if you're hitting data from other partitions, Oracle takes care of pulling those in.

Resources