Processing an OLAP cube with a T-SQL Stored Procedure - tsql

I have simply query in MDX to OLAP cube, like below, and I would like to use this query with a T-SQL stored procedure:
SELECT NON EMPTY { [Measures].[Revenue] } ON COLUMNS,
NON EMPTY { ([Basic].[Payment Method].[Payment Method].ALLMEMBERS ) } ON ROWS
FROM [SummaryCube]
How can I create stored procedure in T-SQL which using this query?

T-SQL and MDX are completely different languages (although they have superficial similarities) so I'm afraid you can't just stuff some MDX into a stored procedure. A quick Google turned up this (making use of linked servers), which looks like it should work for what you want, although you may want to reconsider what you want to achieve and why, before going down this route.

As mentioned in your previous question here: Stored procedure in MDX
Install the addin and then you can do the following:
DECLARE #Server NVARCHAR(30) = 'SummaryCubeServerName';
DECLARE #Database NVARCHAR(50) = 'SummaryCubeDatabaseName';
DECLARE #MDX NVARCHAR(MAX) = '
SELECT
NON EMPTY { [Measures].[Revenue] } ON COLUMNS,
NON EMPTY { ([Basic].[Payment Method].[Payment Method].ALLMEMBERS ) } ON ROWS
FROM [SummaryCube];
'
CREATE TABLE #Results(
PaymentMethod AS VARCHAR(250),
Revenue AS FLOAT
);
INSERT INTO #Results
EXEC ExecuteOLAP #Server, #Database, #MDX;
SELECT *
FROM #Results;
This approach is a lot simpler than using linkedServers and OPENQUERY.

Related

How to declare Array variable in Azure Data Warehouse?

I have a list of strings I use in a sql query similar to this:
select count(*) from sometable where somefield in ('val1','val2',...'valn')
I use this pattern in several queries in a single stored proc. I want to reuse the stored proc, changing the values in the array periodically. Using normal SQL databases, you can declare a table variable type but that is not supported in SQL Data Warehouse. You can use a temp table, but these and table variables require more editing when the values change (requiring insert statements or unions to populate the table). How can I declare an array variable?
Create a varchar variable and use the STRING_SPLIT function in a select statement:
DECLARE #ids varchar(8000)
set #ids = 'Val1,Val2,...ValN'
select count(*) from sometable
where somefield in (SELECT value FROM STRING_SPLIT(#ids, ','))
While this works, I'm not sure how well it scales; for performance reasons, you can fall back to using a temp table - then use VSCode to edit the insert statements (Ctrl+Shift+L is your friend).

Process a row with unknown structure in a cursor

I am new to using cursors for looping through a set of rows. But so far I had prior knowledge of which columns I am about to read.
E.g.
DECLARE db_cursor FOR
SELECT Column1, Column2
FROM MyTable
DECLARE #ColumnOne VARCHAR(50), #ColumnTwo VARCHAR(50)
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #ColumnOne, #ColumnTwo
...
But the tables I am about to read into my key/value table have no specific structure and I should be able to process them one row at a time. How, using a nested cursor, can I loop through all the columns of the fetched row and process them according to their type and name?
TSQL cursors are not really designed to read data from tables of unknown structure. The two possibilities I can think of to achieve something in that direction are:
First read the column names of an unknown table from the Information Schema Views (see System Information Schema Views (Transact-SQL)). Then use dynamic SQL to create the cursor.
If you simply want to get any columns as a large string value, you might also try a simple SELECT * FROM TABLE_NAME FOR XML AUTO and further process the retrieved data for your purposes (see FOR XML (SQL Server)).
SQL is not very good in dealing with sets generically. In most cases you must know column names, data types and much more in advance. But there is XQuery. You can transform any SELECT into XML rather easily and use the mighty abilities to deal with generic structures there. I would not recommend this, but it might be worth a try:
CREATE PROCEDURE dbo.Get_EAV_FROM_SELECT
(
#SELECT NVARCHAR(MAX)
)
AS
BEGIN
DECLARE #tmptbl TABLE(TheContent XML);
DECLARE #cmd NVARCHAR(MAX)= N'SELECT (' + #SELECT + N' FOR XML RAW, ELEMENTS XSINIL);';
INSERT INTO #tmptbl EXEC(#cmd);
SELECT r.value('*[1]/text()[1]','nvarchar(max)') AS RowID
,c.value('local-name(.)','nvarchar(max)') AS ColumnKey
,c.value('text()[1]','nvarchar(max)') AS ColumnValue
FROM #tmptbl t
CROSS APPLY t.TheContent.nodes('/row') A(r)
CROSS APPLY A.r.nodes('*[position()>1]') B(c)
END;
GO
EXEC Get_EAV_FROM_SELECT #SELECT='SELECT TOP 10 o.object_id,o.* FROM sys.objects o';
GO
--Clean-Up for test purpose
DROP PROCEDURE Get_EAV_FROM_SELECT;
The idea in short
The select is passed into the procedure as string. With the SP we create a statement dynamically and create XML from it.
The very first column is considered to be the Row's ID, if not (like in sys.objects) we can write the SELECT and force it that way.
The inner SELECT will read each row and return a classical EAV-list.

Is it possible to use t-SQL to store a hash using HASHBYTES for a file not in the database?

I would just like to know if it is or is not possible to use t-SQL (SQL Server 2012) to store a MD5 hash using HASHBYTES for a file not in the database?
I am only trying to achieve what is stated above without using anything other then T-SQL. That is the constraint weather or not there is a better way. It's a inflexible constraint/mandate that nothing but T-SQL is to be used. No addons no powrshell no nothing but T-SQL.
Can anyone provide the T-SQL code that would achieve the goal of putting the hash of some file (whatever name you want) into a field in a table (use whatever names you prefer)?
I know some might think there is a better way but that better way is not an option like it or not. So please refrain for offering any non 100% T-SQL solutions or comments.
see if this works for you.(tested both text and binary file types)
Declare #x varbinary
Declare #y table ( C1 varbinary(max))
SELECT #x = convert(varbinary , BulkColumn )
FROM OPENROWSET (BULK 'c:\temp\MyFile.txt', SINGLE_CLOB) MyFile
select HASHBYTES('MD5', #x)
insert into #y select HASHBYTES('MD5', #x)
select * from #y
output:
0x93B885ADFE0DA089CDF634904FD59F71
msdn Hashbyte ref:
https://msdn.microsoft.com/en-us/library/ms174415.aspx?f=255&MSPPError=-2147217396
DECLARE #csCommand varchar(4000);
DECLARE #csResult varchar(4000);
DECLARE #result table
([ID] int identity(1,1),
[Output] varchar(4000));
SET #csCommand = 'certutil -hashfile ''C:\Temp\MyFile.txt'' MD5';
INSERT INTO #result ([Output])
EXEC master..xp_cmdshell #csCommand
SELECT #csResult=[Output] FROM #result WHERE ID=2;

How do I select from a stored procedure in Sybase?

My DBA has constructed me a stored procedure in a Sybase database, for which I don't have the definition.
If I run it, it returns a resultset with a set of columns and values. I would like to SELECT further to reduce the rows in the result set. Is this possible?
From this question it seems like I could insert the results into a temporary table, but I'm not sure I've got permissions to do this.
Is there any way I can SELECT certain rows, or if not, can someone give me example code for simulating with a temporary table?
In Sybase ASE, we can use this hack to select from a stored procedure via a "proxy table":
http://www.sypron.nl/proctab.html
Example:
sp_addserver loopback, null, ##servername
go
create existing table
sp_test12 (
Document_Name varchar(100),
Required_Status varchar(5),
Doc_ID varchar(10),
OrderBy int,
No_of_Copy_Retain int,
_p_EPEB_ID varchar(10) null,
_p_MY_NAME varchar(3) null,
_p_MY_NO varchar(10) null,
_p_EPEB_EDATE datetime null,
_TXN varchar(10) null,
_SUBTXN varchar(15) null,
_OwnType_ID1 varchar(5) null,
_OwnType_ID2 varchar(5) null,
_blnflag int null
)
external procedure
at 'loopback.MYDB.dbo.usp_xyz'
go
select
Doc_ID, No_of_Copy_Retain, _p_EPEB_ID, _p_EPEB_ID, _p_MY_NAME, _p_MY_NO
from #sp_test12
where
_p_EPEB_ID='EPEB1508'
and _p_MY_NAME='107'
and _p_MY_NO='2011000045'
and _p_EPEB_EDATE='2011-01-15 15:03:03.0'
and _TXN='TX012'
and _SUBTXN='TX012.001'
and _OwnType_ID1='ASSN'
and _OwnType_ID2='ASSN'
and _blnflag=0
go
Under Sybase IQ (12.6 and higher at least) you can select from a stored procedure and filter the results as if it was a table. I do not know if this works under ASE or ASA but you could give it a try.
So if you stored procedure is called myproc an the result set has a column ACTIVE which can be either 0 or 1 and you want to select only the ACTIVE = 1 rows you could do this.
SELECT * FROM myproc() WHERE ACTIVE = 1
Under IQ you can also use this as a derived table and JOIN it with other tables for example like this...
SELECT t1.name,t1.address,t2,active
FROM tbl_atable t1,
( SELECT * FROM myproc() WHERE ACTIVE = 1) t2
WHERE t1.active = t2.active
...which is kind of neat!
I hope that works for which ever version of Sybase you are running.
You will need to ask the DBA to change the stored procedure.
You could get it changed to select the results into a temporary table rater than a plain select and then you can write your own select on that temp table to return only the rows you want
It is possible with ASE but in a rather roundabout kind of way using CIS and proxy tables. The mechanism is described very well on Rob Verschoor's site:
http://www.sypron.nl/proctab.html
I tried it out once as a curiosity and indeed it does work. I did not delve into the tricky question of error-handling.
pjjH
As far as I know, this is not possible in Sybase ASE. Even using
insert #temp_table
exec my_procedure
doesn't work (at least on sybase 12.x).
Just a thought.
Perhaps your DBA could prepare a view instead of a stored procedure, if he wanted you for some reason not to look at the inner stuff or worry about it.
Another approach would be to see the stored procedure text (unless encrypted) with sp_helptext and rewrite it for your own purposes (eg. into a view) to be able to apply additional conditioning to the resultset.
In Sybase IQ, you can do this:
select < col1>, < col2> from < sp_name>('< sp_arg>') where < predicate>
Example:
select Object, DbspaceName, ObjSize from sp_iqindexinfo ('table xyz') where Object like '%col1_indx%'

Writing Recursive StoredProcedures

Basically what i want in my stored procedure is to return a list of tables, store this list in a variable; i need to go through every item in my list to recursively call this storedprocedure. In the end i need an overall listOfTables built up of this recursion.
Any help would be most appreciated
You should take a look at Common Table Expressions in case you're on SQL2005 or higher (not sure if they can help in your specific situation but an important alternative to most recursive queries) . Recursive procedures cannot nest more than 32 levels deep and are not very elegant.
You can use CTE's:
WITH q (column1, column2) (
SELECT *
FROM table
UNION ALL
SELECT *
FROM table
JOIN q
ON …
)
SELECT *
FROM q
However, there are different limitations: you cannot use aggregates, analytics functions, TOP clause etc.
Are you after recursion or just a loop through all tables? If you are using Sql Server 2005 and want to loop through all tables you can use a table variable in your SP, try something along thse lines:
declare #TableList as table (
ID int identity (1,1),
TableName varchar(500)
)
insert into #TableList (TableName)
select name
from sys.tables
declare #count int
declare #limit int
declare #TableName varchar(500)
set #count = 1
select #limit = max(ID) from #TableList
while #count <= #limit
begin
select #TableName = TableName from #TableList where ID = #count
print #TableName --replace with call to SP
set #count = #count + 1
end
Replace the print #TableName with the call to the SP, and if you don't want this to run on every table in the DB then change the query select name from sys.tables to only return the tables you are after
Most likely a CTE would answer your requirement.
If you really must use a stored procedure not a query then all you have to do is iterate through the table list then you can use your code of choice to iterate through the table list and call the procedure. And Macros already posted how to do that as I was typing lol. And as Mehrdad already told you, there is limit on the number of nested levels of call SQL Server allows and is rather shallow. I'm not convinced from your explanation that you need a recursive call, it looks more like a simple iteration over a list, but if you do indeed need recursivity then remember CS 101 class: any recursive algorithm can be transformed into a non-recursive one by using a loop iteration and a stack.
Stored procedures are very useful. BUT.
I recently had to work on a system that was heavily dependent on stored procedures. It was a nightmare. Half the business logic was in one language (Java, in this case), and the other half was in the database in stored procedures. Worse yet, half the application was under source code control and the other half was one database crash from being lost forever (bad backup processes). Plus, all those lovely little tools I have for scanning, analyzing and maintaining source code can't work with sources inside the database.
I'm not inherently anti-stored-procedure, but oh, how they can be abused. Stored procedures are excellent for when you need to enforce rules against data coming from a multiplicity of sources, and there's no better way to offload heavy-duty record access off the webservers (and onto the DBMS server). But for the most part, I'd rather use a View than a Stored Procedure and an application programming language for the business logic. I know it makes some things a little more complex. But it can make life a whole lot easier.