Using nvarchar(MAX) to build query, but conversion fails in where clause - asp.net

I have a stored procedure that uses a variable called #Command (nvarchar(MAX)). I then add parameters accordingly based on given input.
declare #Command nvarchar(max)
if(#CaseFileID IS NOT NULL)
BEGIN
select #Command='
select [ServerCredentialsID],[CaseFileID],EIKSLT.[LocationType],EPT.PaymentType,[TaskID],[DateActive]
,[LengthOfPurchase],[Username],[Password],[IPDomain],[Port],[DES],[Website],[AmountPaid],[Latitude]
,[Longitude],[HasAttachments],[TimeStamp],[CaseElement],[Temporary],[StatusID]
FROM Element17a_IKSServerCredentials EIKSSC
JOIN ElementsIKSLocationTypes EIKSLT ON EIKSSC.LocationBeingUsedID= EIKSLT.IKSLocationBeingUsedID
JOIN ElementsPaymentTypes EPT ON EIKSSC.PaymentMethodID=EPT.PaymentTypeID
where EIKSSC.CaseFileID='''+cast(#CaseFileID as nvarchar(MAX))+''' '
#CaseFileID is declared as an int, and in the table it is an int. When I try
where EIKSSC.CaseFileID = ' + #CaseFileID + ' '
then the value doesn't even show (in the error it looks like "EIKSSC.CaseFileID= '" )
I just don't get it.
NOTE: SQL Server 2008 Management Studio

It's because #CaseFileID is VARCHAR even though you don't show it.
Your IF should be
if(#CaseFileID > '')
And if even that doesn't work, then you need to swap to LEFT joins because INNER JOINs will remove records that cannot be matched in the other 2 tables.
Finally, because CaseFileID is an int, you don't need the quotes. Even though SQL Server will implicitly cast '9' to the integer 9 in the WHERE clause, it's just not necessary.
declare #Command nvarchar(max)
if(#CaseFileID > '')
BEGIN
select #Command='
select [ServerCredentialsID],[CaseFileID],EIKSLT.[LocationType],EPT.PaymentType,[TaskID],[DateActive]
,[LengthOfPurchase],[Username],[Password],[IPDomain],[Port],[DES],[Website],[AmountPaid],[Latitude]
,[Longitude],[HasAttachments],[TimeStamp],[CaseElement],[Temporary],[StatusID]
FROM Element17a_IKSServerCredentials EIKSSC
LEFT JOIN ElementsIKSLocationTypes EIKSLT ON EIKSSC.LocationBeingUsedID= EIKSLT.IKSLocationBeingUsedID
LEFT JOIN ElementsPaymentTypes EPT ON EIKSSC.PaymentMethodID=EPT.PaymentTypeID
where EIKSSC.CaseFileID='+cast(#CaseFileID as nvarchar(MAX))

Related

Teradata dynamic SQL getting code from another table

I am trying to recreate a query that uses a subquery in the left join to get the value of a KPI. I am trying to store that subquery in another table as a string and use dynamic sql to retrieve that string code and insert it into the left join, but I am getting an error:
[5526] SPL2010:E(L27), Variable of CHARACTER type expected in PREPARE or EXECUTE IMMEDIATE statement.
Here is the procedure I am trying to create. In the variable metric_code, the column SQL is a string that contains the sql code.
Create PROCEDURE dyn_sql_test()
BEGIN
DECLARE metric_code VARCHAR(5000);
Set metric_code = (Select SQL_CODE from mytable_with_Sql_code where ID=1234);
BEGIN
set get_value='
SELECT
e.*
,a.value
FROM Metric_table AS e
LEFT JOIN ('||metric_code||') a
on e.id=a.id
WHERE e.ID = 1234;';
EXECUTE IMMEDIATE get_value;
END;
END;
In case it helps, the string I am retrieving for SQL_CODE, which used to go in the Left Join as a subquery looks something like this:
sel id,type,values
from my_values_table
where type='kpi'

Teradata Insert Count into Variable

Description what I am trying to do:
I have 2 environments one has data (X) second one has no data (Y).
I have done procedure which has input parameter P_TableName. It should check if in this table is any data and IF There is then we will take data to Y environment.
So Mostly it works but I have problem with one freaking simple thing ( I have not much experience in TD but in Oracle it would be a 10seconds).
I need to pass select count(*) from X to variable how to do that?.
I was trying by SET VAR = SELECT...
INSERT INTO VAR SELECT...
I was trying to make a variable for statement which is directly executing
SET v_sql_stmt = 'INSERT INTO ' || VAR|| ' SELECT COUNT(*) FROM ' || P_TableName;
CALL DBC.SYSEXECSQL(v_sql_stmt);
It's probably really simple thing but I can't find good solution for that. Please help
You'll have to open a cursor to fetch the results since you are running dynamic SQL. There is a good example in the Teradata help doc on Dynamic SQL:
CREATE PROCEDURE GetEmployeeSalary
(IN EmpName VARCHAR(100), OUT Salary DEC(10,2))
BEGIN
DECLARE SqlStr VARCHAR(1000);
DECLARE C1 CURSOR FOR S1;
SET SqlStr = 'SELECT Salary FROM EmployeeTable WHERE EmpName = ?';
PREPARE S1 FROM SqlStr;
OPEN C1 USING EmpName;
FETCH C1 INTO Salary;
CLOSE C1;
END;
You can't use INTO in Dynamic SQL in Teradata.
As a workaround you need to do a cursor returning a single row:
DECLARE cnt BIGINT;
DECLARE cnt_cursor CURSOR FOR S;
SET v_sql_stmt = ' SELECT COUNT(*) FROM ' || P_TableName;
PREPARE S FROM v_sql_stmt;
OPEN cnt_cursor;
FETCH cnt_cursor INTO cnt;
CLOSE cnt_cursor;

Run table names pulled from sys.tables SQL Server 2008R2

I need to identify tables that were created today by an interface, which I was able to do by using following query:
Note: The interface changes table names on daily basis.
SELECT [name] AS [TableName]
FROM sys.tables
WHERE NAME LIKE '_XYZExport_%'
AND CAST(create_date AS DATE) = CAST(GETDATE() AS DATE)
ORDER BY NAME
What I need:
Once the table names are pulled, I need dump its data into a new table. How can this be done easily?
Example:
Following tables returned from my queries:
_XYZExport_B02
_XYZExport_B12
_XYZExport_B22
I want to take these returned tables and insert their data into an existing Archive table using Union All.
Any help would be great!
You are on the right track with your "cursor" tag. I would recommend creating an insert statement and executing it each cursor loop.
DECLARE #TableName sysname
DECLARE #SQLInsert VARCHAR(100)
DECLARE TableNamesCursor CURSOR FAST_FORWARD READ_ONLY FOR
SELECT [name] AS [TableName]
FROM sys.tables
WHERE NAME LIKE '_XYZExport_%'
AND CAST(create_date AS DATE) = CAST(GETDATE() AS DATE)
ORDER BY NAME
OPEN TableNamesCursor
FETCH NEXT FROM TableNamesCursor INTO #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQLInsert = 'INSERT INTO ArchiveTable SELECT * FROM ' + #TableName
EXEC sp_executesql #SQLInsert
FETCH NEXT FROM TableNamesCursor INTO #TableName
END
CLOSE TableNamesCursor
DEALLOCATE TableNamesCursor
Hope that gets you going.
Noel

PL/SQL - comma separated list within IN CLAUSE

I am having trouble getting a block of pl/sql code to work. In the top of my procedure I get some data from my oracle apex application on what checkboxes are checked. Because the report that contains the checkboxes is generated dynamically I have to loop through the
APEX_APPLICATION.G_F01
list and generate a comma separated string which looks like this
v_list VARCHAR2(255) := (1,3,5,9,10);
I want to then query on that list later and place the v_list on an IN clause like so
SELECT * FROM users
WHERE user_id IN (v_list);
This of course throws an error. My question is what can I convert the v_list to in order to be able to insert it into a IN clause in a query within a pl/sql procedure?
If users is small and user_id doesn't contain commas, you could use:
SELECT * FROM users WHERE ',' || v_list || ',' LIKE '%,'||user_id||',%'
This query is not optimal though because it can't use indexes on user_id.
I advise you to use a pipelined function that returns a table of NUMBER that you can query directly. For example:
CREATE TYPE tab_number IS TABLE OF NUMBER;
/
CREATE OR REPLACE FUNCTION string_to_table_num(p VARCHAR2)
RETURN tab_number
PIPELINED IS
BEGIN
FOR cc IN (SELECT rtrim(regexp_substr(str, '[^,]*,', 1, level), ',') res
FROM (SELECT p || ',' str FROM dual)
CONNECT BY level <= length(str)
- length(replace(str, ',', ''))) LOOP
PIPE ROW(cc.res);
END LOOP;
END;
/
You would then be able to build queries such as:
SELECT *
FROM users
WHERE user_id IN (SELECT *
FROM TABLE(string_to_table_num('1,2,3,4,5'));
You can use XMLTABLE as follows
SELECT * FROM users
WHERE user_id IN (SELECT to_number(column_value) FROM XMLTABLE(v_list));
I have tried to find a solution for that too but never succeeded. You can build the query as a string and then run EXECUTE IMMEDIATE, see http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/dynamic.htm#i14500.
That said, it just occurred to me that the argument of an IN clause can be a sub-select:
SELECT * FROM users
WHERE user_id IN (SELECT something FROM somewhere)
so, is it possible to expose the checkbox values as a stored function? Then you might be able to do something like
SELECT * FROM users
WHERE user_id IN (SELECT my_package.checkbox_func FROM dual)
Personally, i like this approach:
with t as (select 'a,b,c,d,e' str from dual)
--
select val
from t, xmltable('/root/e/text()'
passing xmltype('<root><e>' || replace(t.str,',','</e><e>')|| '</e></root>')
columns val varchar2(10) path '/'
)
Which can be found among other examples in Thread: Split Comma Delimited String Oracle
If you feel like swamping in even more options, visit the OTN plsql forums.

Preferred Method to Catch Specific OleDB Error

Ok - I have a situation in which I must execute a dynamically built stored procedure against tables that may, or may not be in the database. The data retrieved is then shunted to a VB.Net backed ASP based report page. By design, if the tables are not present in the database, the relevant data is automatically hidden on the report page. Currently, I'm doing this by checking for the inevitable error, and hiding the div in the catch block. A bit kludgy, but it worked.
I can't include the VB code-behind, but the relevant stored procedure is included below.
However, a problem with this method was recently brought to my attention when, for no apparent reason, the div was being hidden even though the proper data was available. As it turned out, the user trying to select the table in the dynamic SQL call didn't have the proper select permissions, an easy enough fix once I could track it down.
So, two fold question. First and foremost - is there a better way to check for a missing table than through catching the error in the VB.Net codebehind? All things considered, I'd rather save the error checking for an actual error. Secondly, is there a preferred method to squirrel out a particular OLE DB error out of the general object caught by the try->catch block other than just checking the actual stack trace string?
SQL Query - The main gist of the code is that, due to the design of the database, I have to determine the name of the actual table being targeted manually. The database records jobs in a single table, but each job also gets its own table for processing data on the items processed in that job, and it's data from those tables I have to retrieve. Absolutely nothing I can do about this setup, unfortunately.
DECLARE #sql NVarChar(Max),
#params NVarChar(Max),
#where NVarChar(Max)
-- Retained for live testing of stored procedure.
-- DECLARE #Table NvarChar(255) SET #Table = N'tblMSGExportMessage_10000'
-- DECLARE #AcctID Integer SET #AcctID = 10000
-- DECLARE #Type Integer SET #Type = 0 -- 0 = Errors only, 1 = All Messages
-- DECLARE #Count Integer
-- Sets our parameters for our two dynamic SQL calls.
SELECT #params = N'#MsgExportAccount INT, #cnt INT OUTPUT'
-- Sets our where clause dependent upon whether we want all results or just errors.
IF #Type = 0
BEGIN
SELECT #where =
N' AND ( mem.[MSGExportStatus_OPT_CD] IN ( 11100, 11102 ) ' +
N' OR mem.[IngestionStatus_OPT_CD] IN ( 11800, 11802, 11803 ) ' +
N' OR mem.[ShortcutStatus_OPT_CD] IN ( 11500, 11502 ) ) '
END
ELSE
BEGIN
SELECT #where = N' '
END
-- Retrieves a count of messages.
SELECT #sql =
N'SELECT #cnt = Count( * ) FROM dbo.' + QuoteName( #Table ) + N' AS mem ' +
N'WHERE mem.[MSGExportAccount_ID] = #MsgExportAccount ' + #where
EXEC sp_executesql #sql, #params, #AcctID, #cnt = #Count OUTPUT
To avoid an error you could query the sysobjects table to find out if the table exists. Here's the SQL (replace YourTableNameHere). If it returns > 0 then the table exists. Create a stores procedure on the server that runs this query.
select count(*)
from sysobjects a with(nolock)
where a.xtype = 'U'
and a.name = 'YourTableNameHere'

Resources