operations with time firebird - firebird

To resolve the issue.
There are two meanings Time: 12:20 and 23:55. How can add the values that-be at the outlet was 36:15.
Or how to keep these values in dB (Time) Time except that, were it possible addition?

Firebird's data type TIME allows range between 00:00:00 and 24:00:00 only.
If you want to store arbitrary amount of time (say, in seconds) use INTEGER or NUMERIC datatype. Then convert it into time string format if needed.

You can use TIMESTAMP in dialect 3
With this you can add 2 times.

i have code here convert seconds in integer
CREATE PROCEDURE P_CONVERT_TIME (
V_TIME_INT INTEGER
)
RETURNS (
V_TIME_STR VARCHAR(20)
)
AS
DECLARE VARIABLE v_max_trans_hour integer;
DECLARE VARIABLE v_max_trans_min integer;
DECLARE VARIABLE v_max_trans_sec integer;
DECLARE VARIABLE v_max_trans_sec_gross integer;
BEGIN
v_max_trans_sec = cast(v_Time_Int as integer);
v_max_trans_hour = coalesce(div(v_max_trans_sec, 3600), 0);
if (v_max_trans_hour > 0) then
v_max_trans_sec = v_max_trans_sec - (3600 * v_max_trans_hour);
v_max_trans_min = coalesce(div(v_max_trans_sec, 60), 0);
if (v_max_trans_min > 0) then
v_max_trans_sec = v_max_trans_sec - (60 * v_max_trans_min);
if (v_max_trans_hour > 0) then begin
if (v_max_trans_hour < 10) then begin
V_Time_Str ='0'||v_max_trans_hour||':'; end else
V_Time_Str=v_max_trans_hour||':';
end else V_Time_Str='00:';
if (v_max_trans_min > 0) then begin
if (v_max_trans_min <10) then begin
V_Time_Str =V_Time_Str ||'0'||v_max_trans_min||':'; end else
V_Time_Str =V_Time_Str ||v_max_trans_min||':';
end else V_Time_Str =V_Time_Str ||'00:';
if (v_max_trans_sec > 0) then begin
if (v_max_trans_sec <10) then begin
V_Time_Str =V_Time_Str ||'0'|| v_max_trans_sec; end else
V_Time_Str =V_Time_Str || v_max_trans_sec;
end else V_Time_Str =V_Time_Str ||'00';
suspend;
END
;

Related

Cannot convert string to decimal number - T-sql

I used this function to extract decimal numbers from a string:
ALTER Function [dbo].[udf_ExtractNumber] (#String nvarchar(256))
RETURNS nvarchar(max)
AS
BEGIN
DECLARE #AlphaNumeric varchar(256)
,#Res varchar(256)
SET #AlphaNumeric = #String
SET #Res = NULL
WHILE (PATINDEX('%[0-9]%', #AlphaNumeric) > 0 )
BEGIN
IF (PATINDEX('%[0-9]%', #AlphaNumeric) >0 AND PATINDEX('%[0-9]%', #AlphaNumeric) < CHARINDEX(',', #AlphaNumeric))
BEGIN
SET #Res = CONCAT(#Res ,SUBSTRING(#AlphaNumeric, PATINDEX('%[0-9]%', #AlphaNumeric), 1) )
SET #AlphaNumeric = RIGHT(#AlphaNumeric,len(#AlphaNumeric)- PATINDEX('%[0-9]%', #AlphaNumeric))
END
ELSE IF (CHARINDEX(',', #AlphaNumeric) >0 AND CHARINDEX(',', #AlphaNumeric) < PATINDEX('%[0-9]%', #AlphaNumeric))
BEGIN
SET #Res = CONCAT(#Res ,SUBSTRING(#AlphaNumeric, CHARINDEX(',', #AlphaNumeric), 1) )
SET #AlphaNumeric = RIGHT(#AlphaNumeric,len(#AlphaNumeric)- CHARINDEX(',', #AlphaNumeric))
END
ELSE IF (PATINDEX('%[0-9]%', #AlphaNumeric) >0)
BEGIN
SET #Res = CONCAT(#Res, SUBSTRING(#AlphaNumeric, PATINDEX('%[0-9]%', #AlphaNumeric), 1) )
SET #AlphaNumeric = RIGHT(#AlphaNumeric,len(#AlphaNumeric)- PATINDEX('%[0-9]%', #AlphaNumeric))
END
ELSE IF (CHARINDEX(',', #AlphaNumeric) >0 )
BEGIN
SET #Res = CONCAT(#Res,SUBSTRING(#AlphaNumeric, CHARINDEX(',', #AlphaNumeric), 1))
SET #AlphaNumeric = RIGHT(#AlphaNumeric,len(#AlphaNumeric)- CHARINDEX(',', #AlphaNumeric))
END
END
Return #Res
This is working fine, output is exactly what i want.
It converts for example "adsfadf 18,12 adfasdsfa" to 18,12
However, when I want to work with the number I cannot convert it to a float.
Dividing or multiplying it gives the following error:
Conversion failed when converting the nvarchar value '7,5' to data type int.
Based on comments of Ali Fidenli, I adjust the last part of the code to get it working. Thanks
END
Return replace(#Res,',','.')

INTERVAL add i day is not working in postgresql

I have a table like this:
CREATE TABLE DateInsert(
DateInsert timestamp without time zone,
DateInt integer NOT NULL
);
I want insert list day from 2018-01-01 to 2045-05-18 but it give me an erro
"invalid input syntax for type interval:"
CREATE OR REPLACE FUNCTION insertdate() RETURNS integer AS $$
DECLARE i integer := 0;
d timestamp without time zone := '2018-01-01';
di integer := 0;
BEGIN
while i <10000
LOOP
d := d + INTERVAL ''+ i::character varying + ' day';
di := to_char(d , 'yyyymmdd')::int;
insert into DateInsert(DateInsert,DateInt) values(d, di);
i := i+1;
END LOOP ;
return i;
END;
$$ LANGUAGE plpgsql;
How can I insert to db with timestamp increase 1 in n day loop?
Code In sql server has been working.
declare #i int=0
declare #d datetime
declare #di int = 0
while #i <10000
begin
set #d = DATEADD(DAY, #i, '2018-01-01')
set #di = cast(CONVERT(VARCHAR(10), #d, 112) as int)
insert into DateInsert(DateInsert,DateInt) values(#d, #di)
set #i = #i+1
end
The concatenation operator is || not +. And the prefixed form doesn't seem to like anything else than literals. But you can cast the concatenation expression.
So changing
...
d := d + INTERVAL ''+ i::character varying + ' day';
...
to
...
d := d + (i || ' day')::interval;
...
should work for you.

Syntax error at or near ","

I have problems with this function and couldn't figure out how to fix it.
Create Function Quy(sdate timestamp)
returns integer as $$
declare
numbmonth integer;
quy integer;
Begin
numbmonth := Date_part('month',sdate);
If numbmonth < 4 then
quy := 1;
else if numbmonth < 7 then
quy := 2;
else if numbmonth < 10 then
quy := 3;
else quy := 4;
return quy;
END;
$$
LANGUAGE plpgsql;
This happens when I try to run the code:
ERROR: syntax error at or near ";"
LINE 16: END;
I really don't understand what is wrong with this.
Multiple syntax errors. The function would work like this:
CREATE OR REPLACE FUNCTION quy(sdate timestamp)
RETURNS integer AS
$func$
DECLARE
numbmonth integer := date_part('month', sdate);
quy integer;
BEGIN
IF numbmonth < 4 THEN
quy := 1;
ELSIF numbmonth < 7 THEN
quy := 2;
ELSIF numbmonth < 10 THEN
quy := 3;
ELSE
quy := 4;
END IF;
RETURN quy;
END
$func$ LANGUAGE plpgsql;
Consult the manual for the basic syntax of IF.
But that's much ado about nothing. To get the quarter of the year use the field specifier QUARTER with date_part() or EXTRACT() in a simple expression:
EXTRACT(QUARTER FROM $timestamp)
EXTRACT is the standard SQL equivalent of date_part().
Either returns double precision, so cast to integer if you need that (::int).
If you still need a function:
CREATE OR REPLACE FUNCTION quy(sdate timestamp)
RETURNS int LANGUAGE sql IMMUTABLE AS
'SELECT EXTRACT(QUARTER FROM $1)::int';
$1 is the reference to the 1st function parameter. Equivalent to sdate in the example. $-notation works in any version of Postgres, while named parameter references in SQL functions were only introduced with Postgres 9.2. See:
PLPGSQL Function to Calculate Bearing
dbfiddle here

Recursive SQL function, <= operator doesn't work

I just wonder why this works. But what I have comment doesn't work.
ALTER PROC spFactorial
#ValueIn int,
#ValueOut int OUTPUT
AS
DECLARE #InWorking int;
DECLARE #OutWorking int;
IF #ValueIn <> 1 -- this <= doesn't work??
BEGIN
SELECT #InWorking = #ValueIn - 1;
EXEC spFactorial #InWorking, #OutWorking OUTPUT;
SELECT #ValueOut = #ValueIn * #OutWorking;
END
ELSE
BEGIN
SELECT #ValueOut = 1;
END
RETURN;
GO
DECLARE #WorkingOut int;
DECLARE #WorkingIn int;
SELECT #WorkingIn = 3;
EXEC spFactorial #WorkingIn, #WorkingOut OUTPUT;
PRINT CAST(#WorkingIn AS varchar ) + ' factorial is '
+ CAST(#WorkingOut AS VARCHAR );
This IF #ValueIn <= 1 doesn't work - why?
In C# or java it works.
Thank you
<= is not an operator in SQL. In c# and Java it is.
For <= operator functionality in Sql, you can do this
IF(#value < 1 OR #value = 1)

Is there any hash function in PostgreSQL?

I am using Sphinx to index my database.
The problem is I have to filter the result by a character varying field.
So I have to find a way to convert character varying to sql_attr_uint.
I know that CRC32 in mysql can do the trick. Is there a CRC32 or any replacement in PostgreSQL?
This is the CRC32 function that defines thinking sphinx (gem):
CREATE OR REPLACE FUNCTION crc32(word text)
RETURNS bigint AS $$
DECLARE tmp bigint;
DECLARE i int;
DECLARE j int;
DECLARE byte_length int;
DECLARE word_array bytea;
BEGIN
IF COALESCE(word, '') = '' THEN
return 0;
END IF;
i = 0;
tmp = 4294967295;
byte_length = bit_length(word) / 8;
word_array = decode(replace(word, E'\\\\', E'\\\\\\\\'), 'escape');
LOOP
tmp = (tmp # get_byte(word_array, i))::bigint;
i = i + 1;
j = 0;
LOOP
tmp = ((tmp >> 1) # (3988292384 * (tmp & 1)))::bigint;
j = j + 1;
IF j >= 8 THEN
EXIT;
END IF;
END LOOP;
IF i >= byte_length THEN
EXIT;
END IF;
END LOOP;
return (tmp # 4294967295);
END
$$ IMMUTABLE LANGUAGE plpgsql;
Maybe you can use decode(substring(md5('foo') for 8), 'hex'). This would get you bytea of first 4 bytes of md5 hash of this string.
You can convert it to integer using something like:
create function bytea_to_integer(bytea)
returns integer strict
language sql as $$
select
(get_byte($1,0)*1::integer<<0*8)
+(get_byte($1,1)*1::integer<<1*8)
+(get_byte($1,2)*1::integer<<2*8)
+(get_byte($1,3)*1::integer<<3*8);
$$;