Simple Firebird Query - database

I am trying to do a while loop in Firebird to execute all the values from an SP using FlameRobin tool. However this is not working. Any suggestion?
declare i int = 0;
while ( i <= 2 ) do BEGIN
SELECT p.SOD_AUTO_KEY, p.CURRENCY_CODE, p.SO_CATEGORY_CODE, p.SO_NUMBER, p.INVC_NUMBER, p.ENTRY_DATE, p.SHIP_DATE, p.NEXT_SHIP_DATE, p.CONDITION_CODE, p.QTY_ORDERED, p.QTY_PENDING_INVOICE, p.QTY_INVOICED, p.UNIT_PRICE, p.EXCHANGE_RATE, p.UNIT_COST, p.ITEM_NUMBER, p.CONSIGNMENT_CODE, p.NOTES, p.STOCK_LINE, p.STM_AUTO_KEY, p.SERIAL_NUMBER, p.REMARKS, p.PN, p.PNM_AUTO_KEY, p.GR_CODE, p.CUSTOMER_PRICE, p.OPEN_FLAG, p.ROUTE_CODE, p.ROUTE_DESC, p.COMPANY_CODE, p.SITE_CODE, p.COMPANY_NAME, p.COMPANY_REF_NUMBER, p.CUST_REF, p.HOT_PART
FROM SPB_SALESHISTORY(i) p
i = i + 1;
end
Error Message I get:
Preparing query: declare i int = 0
Error: *** IBPP::SQLException ***
Context: Statement::Prepare( declare i int = 0 )
Message: isc_dsql_prepare failed
SQL Message : -104
can't format message 13:896 -- message file C:\Windows\firebird.msg not found
Engine Code : 335544569
Engine Message :
Dynamic SQL Error
SQL error code = -104
Token unknown - line 1, column 9
i
Total execution time: 0.004s
This is what I tried but it only says "Script Execution Finished" and does not return any results:
set term !!
EXECUTE BLOCK returns(p) AS
declare i integer = 0
BEGIN
while ( i <= 1000 ) do BEGIN
SELECT p.SOD_AUTO_KEY, p.CURRENCY_CODE, p.SO_CATEGORY_CODE, p.SO_NUMBER, p.INVC_NUMBER, p.ENTRY_DATE, p.SHIP_DATE, p.NEXT_SHIP_DATE, p.CONDITION_CODE, p.QTY_ORDERED,p.QTY_PENDING_INVOICE, p.QTY_INVOICED, p.UNIT_PRICE, p.EXCHANGE_RATE, p.UNIT_COST, p.ITEM_NUMBER, p.CONSIGNMENT_CODE, p.NOTES, p.STOCK_LINE, p.STM_AUTO_KEY, p.SERIAL_NUMBER, p.REMARKS, p.PN, p.PNM_AUTO_KEY, p.GR_CODE, p.CUSTOMER_PRICE, p.OPEN_FLAG, p.ROUTE_CODE, p.ROUTE_DESC, p.COMPANY_CODE, p.SITE_CODE, p.COMPANY_NAME, p.COMPANY_REF_NUMBER, p.CUST_REF, p.HOT_PART
FROM SPB_SALESHISTORY(i) p
i = i + 1
end
END !!
Mark,
I tried your suggestion however I got the following error:
set term!!;
EXECUTE BLOCK RETURNS (
SOD_AUTO_KEY Integer,
CURRENCY_CODE Char(3),
SO_CATEGORY_CODE Char(10),
SO_NUMBER Char(12),
INVC_NUMBER Char(12),
ENTRY_DATE Timestamp,
SHIP_DATE Timestamp,
NEXT_SHIP_DATE Timestamp,
CONDITION_CODE Varchar(10),
QTY_ORDERED Double precision,
QTY_PENDING_INVOICE Double precision,
QTY_INVOICED Double precision,
UNIT_PRICE Double precision,
EXCHANGE_RATE Double precision,
UNIT_COST Double precision,
ITEM_NUMBER Integer,
CONSIGNMENT_CODE Char(10),
NOTES Blob sub_type 1,
STOCK_LINE Integer,
STM_AUTO_KEY Integer,
SERIAL_NUMBER Varchar(40),
REMARKS Varchar(50),
PN Varchar(40),
PNM_AUTO_KEY Integer,
GR_CODE Varchar(10),
CUSTOMER_PRICE Double precision,
OPEN_FLAG Char(1),
ROUTE_CODE Char(1),
ROUTE_DESC Varchar(20),
COMPANY_CODE Varchar(10),
SITE_CODE Varchar(10),
COMPANY_NAME Varchar(50),
COMPANY_REF_NUMBER Varchar(30),
CUST_REF Varchar(15),
HOT_PART Char(1)
)
AS
declare i integer;
BEGIN
i=0;
while ( i <= 2 ) do
BEGIN
for SELECT SOD_AUTO_KEY,CURRENCY_CODE,SO_CATEGORY_CODE, SO_NUMBER,INVC_NUMBER,ENTRY_DATE, SHIP_DATE, NEXT_SHIP_DATE, CONDITION_CODE, QTY_ORDERED,QTY_PENDING_INVOICE, QTY_INVOICED, UNIT_PRICE, EXCHANGE_RATE, UNIT_COST,ITEM_NUMBER, CONSIGNMENT_CODE, NOTES, STOCK_LINE, STM_AUTO_KEY, SERIAL_NUMBER,REMARKS, PN, PNM_AUTO_KEY, GR_CODE, CUSTOMER_PRICE, OPEN_FLAG, ROUTE_CODE,ROUTE_DESC, COMPANY_CODE, SITE_CODE, COMPANY_NAME, COMPANY_REF_NUMBER, CUST_REF, HOT_PART
FROM SPB_SALESHISTORY (i)
into :SOD_AUTO_KEY, :CURRENCY_CODE, :SO_CATEGORY_CODE, :SO_NUMBER, :INVC_NUMBER,
:ENTRY_DATE, :SHIP_DATE, :NEXT_SHIP_DATE, :CONDITION_CODE, :QTY_ORDERED,:QTY_PENDING_INVOICE,
:QTY_INVOICED, :UNIT_PRICE, :EXCHANGE_RATE, :UNIT_COST, :ITEM_NUMBER, :CONSIGNMENT_CODE, :NOTES, :STOCK_LINE,
:STM_AUTO_KEY, :SERIAL_NUMBER, :REMARKS, :PN, :PNM_AUTO_KEY, :GR_CODE, :CUSTOMER_PRICE, :OPEN_FLAG, :ROUTE_CODE,:ROUTE_DESC,
:COMPANY_CODE, :SITE_CODE, :COMPANY_NAME, :COMPANY_REF_NUMBER, :CUST_REF,:HOT_PART
DO
suspend;
i = i + 1;
end
END!!
SET TERM;!!
Error:
Message: isc_dsql_prepare failed
SQL Message : -206
can't format message 13:794 -- message file C:\Windows\firebird.msg not found
Engine Code : 335544569
Engine Message :
Dynamic SQL Error
SQL error code = -206
Column unknown
I
At line 46, column 27
Total execution time: 0.005s

Based on your comments on the answer of Ain, it looks like you also want to return the selected values from the EXECUTE BLOCK. Your RETURNS (p) is invalid and will not work. You need to explicitly declare all columns you want to return, and you need to SUSPEND each row.
In addition you are also forgetting several statement terminators (;), and you can't declare the variable and its value together. The resulting execute block would be something like:
set term !!;
EXECUTE BLOCK returns (
SOD_AUTO_KEY INTEGER,
/* ... */
HOT_PART VARCHAR(255)
) AS
declare i integer;
BEGIN
i = 0;
while ( i <= 1000 ) do
BEGIN
FOR SELECT SOD_AUTO_KEY, /* ... */ HOT_PART
FROM SPB_SALESHISTORY(i)
INTO :SOD_AUTO, /* ... */ :HOT_PART
DO
SUSPEND;
i = i + 1;
end
END!!
SET TERM ;!!
I have left out some of the columns for brevity and guessed at their types.

No, you can't execute such scripts directly in Flamerobin's query window. I think simplest way would be to wrap your script into an stored procedure which you would drop after you're done with the result. To create the temp SP right-click on the Procedures node in the Flamerobin's database tree and select Create new - this creates the SP sceleton for you where you can insert your code.

You will need to wrap your stored procedure like code in a EXECUTE BLOCK statement.

Your sql script may be corrupted

Related

SQL Server float comparison in stored procedure

Unfortunately, I have two tables to compare float datatypes between. I've read up on trying casts, converts, using a small difference and tried them all.
The strange part is, this only fails when I'm executing a stored procedure. If I cut-and-paste the body of the stored procedure into a SSMS window, it works just great.
Sample SQL:
set #newEnvRiskLevel = -1
select
#newEnvRiskLevel = rl.RiskLevelId
from
LookupTypes lt
inner join
RiskLevels rl on lt.LookupTypeId = rl.RiskLevelTypeFk
where
lt.Code = 'RISK_LEVEL_ENVIRONMENTAL'
and convert(numeric(1, 0), rl.RiskFactor) = #newEnvScore
set #errorCode = ##ERROR
if (#newEnvRiskLevel = -1 or #errorCode != 0)
begin
print 'newEnvScore = ' + cast(#newEnvScore as varchar) + ' and risk level = ' + cast(isnull(#newEnvRiskLevel, -1) as varchar)
print 'ERROR finding environmental risk level for code ' + #itemCode + ', skipping record'
set #recordsErrored = #recordsErrored + 1
goto NEXTREC
end
My #newEnvScore variable is also a float converted to numeric(1, 0). I've verified that there are only 0, 1, 2, and 3 for values in the RiskFactor column, and (via debug) that #newEnvScore has a value of 2. I've also verified that my query has a row with code = 'RISK_LEVEL_ENVIRONMENTAL' and RiskFactor = 2.
I've verified via debug that failure is due to #newEnvRiskLevel staying at -1 and that #errorCode is 0.
I've also tried cast to both decimal and int, convert to int, and "rl.RiskFactor - #newEnvScore < 1" in my where clause, none of which set newEnvRiskLevel.
As I say, it's only when running this as a stored procedure that failure happens, which is the part I really don't understand. I'd expect SQL Server to be deterministic, whether the SQL is running the body of a stored procedure, or running the exact same SQL in a SSMS tab.
It is unfortunate that you do post neither your stored procedure nor a complete script. It is difficult to diagnose a problem without a useful demonstration. But I see the use of "goto" which is concerning in many ways. I also see the use of a select statement to assign a local variable - which is often a problem because the developer might be assuming an assignment always occurs. To demonstrate - with a bonus at the end
set nocount on;
declare #risk smallint;
declare #risklevels table (risklevel float primary key, code varchar(10));
insert #risklevels(risklevel, code) values (1, 'test'), (2, 'test'), (-5, 'test');
-- here is your assignment logic. Notice that #risk is
-- never changed because there are no matching rows.
set #risk = 0;
select #risk = risklevel from #risklevels where code = 'zork';
select #risk;
-- here is a better IMO way to make the assignment. Note that
-- #risk is set to NULL when there are no matching rows.
set #risk = -1;
set #risk = (select risklevel from #risklevels where code = 'zork');
select #risk;
-- and a last misconception. What value is #risk set to? and why?
set #risk = -1;
select #risk = risklevel from #risklevels where code = 'test';
select #risk;
Whether this is the source of your problem (or contributes to it) I can't say. But it is a possibility. And storing integers in a floating point datatype is just a problem generally. Even if you cannot change your table, you can change your local variables and force the use of a more appropriate datatype. So perhaps that is another change you should consider.

Sql server and R, data mining

I'm working on Microsoft SQL Management Studio 2016, using the feature that make me to add an R script into the SQL code.
My goals is to achieve an aPriori algorithm procedure, that puts the data in a manner that I like, i.e. a table with x, first object, y, second object.
I am stuck here, because in my opinion I have some problem in data. The error is this.
A 'R' script error occurred during execution of
'sp_execute_external_script' with HRESULT 0x80004004.
An external script error occurred: Error in eval(expr, envir, enclos)
: bad allocation Calls: source -> withVisible -> eval -> eval -> .Call
Here my code.
The source data are a table of two column like this:
A B
a f
f a
b c
...
y z
And here the code:
GO
create procedure dbo.apriorialgorithm as
-- delete old table
IF OBJECT_ID('Data') IS NOT NULL
DROP TABLE Data
-- create a table that store the query result.
CREATE TABLE Data ( art1 nvarchar(100), art2 nvarchar(100));
-- store the query
INSERT INTO Data ( art1, art2)
select
firstfield as art1,
secondfield as art2
from allthefields
;
IF OBJECT_ID('output') IS NOT NULL
DROP TABLE output
-- create table of the results of the analysis.
CREATE TABLE output (x nvarchar(100), y nvarchar(100));
INSERT INTO output (x, y)
-- R script.
EXECUTE sp_execute_external_script
#language = N'R'
, #script = N'
Now the R script. The data that I get from the query are numeric, but for the apriori, I need factors, so first I bend the data to factor;
df<-data.frame(x=as.factor("art1"),y=as.factor("art2"))
Then, I can apply the apriori:
library("arules");
library("arulesViz");
rules = apriori(df,parameter=list(minlen=2,support=0.05, confidence=0.05));
I need the data without the format of the rules, but simply the objects:
ruledf <- data.frame(
lhs <- labels(lhs(rules)),
rhs <- labels(rhs(rules)),
rules#quality)
a<-substr(ruledf$lhs,7,nchar(as.character( ruledf$lhs))-1)
b<-substr(ruledf$rhs,7,nchar(as.character( ruledf$rhs))-1)
ruledf2<-data.frame(a,b)
'
And the last part:
, #input_data_1 = N'SELECT * from Data'
, #output_data_1_name = N'ruledf2'
, #input_data_1_name = N'ruledf2';
GO
I do not know where I am failing, because doing the same things in R using RODBC to catch the db data, everything is ok.
Could you help me? Thanks in advance!
The problem was here, the R script is better this way:
EXECUTE sp_execute_external_script
#language = N'R'
, #script = N'
library("arules");
rules = apriori(df[, c("art1", "art2")], parameter=list(minlen=2,support=0.0005, confidence=0.0005));
ruledf <- data.frame(
lhs <- labels(lhs(rules)),
rhs <- labels(rhs(rules)),
rules#quality)
ruledf2<-data.frame(
lhs2<-substr(ruledf$lhs,7,nchar(as.character( ruledf$lhs))-1),
rhs2<-substr(ruledf$rhs,7,nchar(as.character( ruledf$rhs))-1)
)
colnames(ruledf2)<-c("a","b") '
Then it needs to have the right input and output:
, #input_data_1 = N'SELECT * from Data'
, #input_data_1_name = N'df'
, #output_data_1_name = N'ruledf2'
So the result is going to be a table named output like this
x y
artA artB
artB artA
...
artY artZ
Very helpful this.

How do i format a sql numeric type with commas on Sybase SQLAnywhere?

I came across the following solution but it does not work on Sybase
SELECT CONVERT(varchar, CAST(987654321 AS money), 1)
I have read the Convert Sybase information but still i receive the same number without the commas.
Have you tried giving a varchar (20) for example instead ? something like :
SELECT CONVERT(varchar(20), CAST(987654321 AS money), 1)
In SqlAnywhere money datatype is a domain, implemented as NUMERIC(19,4).
in CAST function , If you do not indicate a length for character string types, the database server chooses an appropriate length. If neither precision nor scale is specified for a DECIMAL conversion, the database server selects appropriate values.
So maybe this is what's causing the issue, what do you get as output ? do you get 987654321.00 , or just 987654321 ?
Update:
My last suggestion would be using insertstr() function and loop through the char value of your number to insert comma every 3 digits .. this is not the cleanest/easiest way but apparently SQLAnywhere deal with money datatype as normal NUMERIC datatype ...
insertstr() documentation is here.
I would give you a code sample but I don't have SQLAnywhere installed to test it ...
Here is the SP i created based on F Karam suggestion.
CREATE FUNCTION "DBA"."formattednumber"( in #number numeric)
returns char(60)
begin
declare #returnnumber char(60);
declare #workingnumber char(60);
declare #n_ind char(1);
declare #decimalnumber char(10);
declare #tempnumber char(60);
declare #decimalpos integer;
if isnull(#number,'') = '' then
return null
end if;
if #number < 0 then set #n_ind = 'Y'
else set #n_ind = 'N'
end if;
set #workingnumber = convert(char(60),ABS(#number));
set #decimalpos = patindex('%.%',#workingnumber);
if #decimalpos > 0 then
set #decimalnumber = substr(#workingnumber,#decimalpos);
set #decimalnumber = "left"(#decimalnumber,3+1);
set #workingnumber = "left"(#workingnumber,#decimalpos-1)
end if end if;
set #returnnumber = '';
while length(#workingnumber) > 3 loop
set #tempnumber = "right"(#workingnumber,3);
set #returnnumber = insertstr(0,#returnnumber,#tempnumber);
set #workingnumber = "left"(#workingnumber,length(#workingnumber)-3);
if length(#workingnumber) > 0 then
set #returnnumber = insertstr(0,#returnnumber,',')
end if
end loop;
if length(#workingnumber) > 0 then
set #returnnumber = insertstr(0,#returnnumber,#workingnumber)
end if;
if length(#decimalnumber) > 0 then
set #returnnumber = #returnnumber+#decimalnumber
end if;
if #n_ind = 'Y' then set #returnnumber = '-' || #returnnumber
end if;
return(#returnnumber)
end;
You need to distinguish between server-side and client-side formatting. When you use the 'isql' client for example (the TDS client), then the result will be this:
1> select convert(money, 9876543210)
2> go
9876543210
------------------------
9,876,543,210.00
(1 row affected)
But this is purely because the client application happens to format 'money' values this way. Also, this is actually not specific for SQLA, since isql is originally the client tool for ASE (a different Sybase database).
When you run the same conversion at the SQLA server (i.e. as part of an expression in a SQL statement), those commas will not be there since SQLA doesn't have such a built-in formatting style.
If you want this, you should write a SQL function that formats the number as you desire.

How to write these kind of functions in solr data config.xml

CREATE OR REPLACE FUNCTION page(IN i_app name character varying, IN i_photo_id big int, IN i_page integer, IN i_member_id big int, OUT o_similar_page_name character varying, OUT o_similar_page_id big int, OUT o_similar_photo_id big int[])
DECLARE
v_limit INTEGER := 4;
v_offset INTEGER;
BEGIN
SET SEARCH_PATH = '';
v_start_time = DAYTIME();
i_app name = UPPER(i_app name);
IF i_app name <> 'DD' THEN
RAISE EXCEPTION 'Enter Valid Application Name';
END IF;
IF i_page = 1 THEN
v_offset := 0;
ELSE
v_offset := i_page * v_limit - v_limit;
END IF;
Please help me.
Answer
No.
Reason
Its not actually the purpose of SOLR. Functions has to be written in the DB level and the data that is retrieved out of query will be stored in SOLR for fast retrieval.
ALTERNATIVE SOLUTION
You can create the function and call it in the select statement to index the data into SOLR.
Note : Final results fetched out of functions can be stored in the SOLR.
Example:
CREATE FUNCTION CustomerLevel(p_creditLimit double) RETURNS VARCHAR(10)
DETERMINISTIC
BEGIN
DECLARE lvl varchar(10);
IF p_creditLimit > 50000 THEN
SET lvl = 'PLATINUM';
ELSEIF (p_creditLimit <= 50000 AND p_creditLimit >= 10000) THEN
SET lvl = 'GOLD';
ELSEIF p_creditLimit < 10000 THEN
SET lvl = 'SILVER';
END IF;
RETURN (lvl);
END
Query to used in SOLR for Indexing
SELECT CustomerLevel(123123123) as CustomerLevel from CustomerRating;

Number 0 is not saving to database as a prefix in SQL Server of CHAR data type column

I am trying to insert an value as '019393' into a table with a CHAR(10) column.
It is inserting only '19393' into the database
I am implementing this feature in a stored procedure, doing some manipulation like incrementing that number by 15 and saving it back with '0' as the prefix
I am using SQL Server database
Note: I tried CASTING that value as VARCHAR before saving to the database, but even that did not get the solution
Code
SELECT
#fromBSB = fromBSB, #toBSB = toBSB, #type = Type
FROM
[dbo].[tbl_REF_SpecialBSBRanges]
WHERE
CAST(#inputFromBSB AS INT) BETWEEN fromBSB AND toBSB
SET #RETURNVALUE = #fromBSB
IF(#fromBSB = #inputFromBSB)
BEGIN
PRINT 'Starting Number is Equal';
DELETE FROM tbl_REF_SpecialBSBRanges
WHERE Type = #type AND fromBSB = #fromBSB AND toBSB = #toBSB
INSERT INTO [tbl_REF_SpecialBSBRanges] ([Type], [fromBSB], [toBSB])
VALUES(#type, CAST('0' + #fromBSB + 1 AS CHAR), #toBSB)
INSERT INTO [tbl_REF_SpecialBSBRanges] ([Type], [fromBSB], [toBSB])
VALUES(#inputBSBName, #inputFromBSB, #inputToBSB)
END
Okay, without knowing the column datatypes, I would suggest trying this:
Change from
CAST('0'+#fromBSB+1 AS CHAR)
To
'0'+CAST(#fromBSB+1 AS CHAR(10))
But if the columns are integers this won't make a difference.

Resources