I have the float value to remove the white space from it.
Here is the following is the example.
In SQL Server: In SQL Server I used the following script.
DECLARE #f1 FLOAT = 74.3658319091568;
SELECT REPLACE(#f1,CHAR(160),'');
--Output
74.3658
PostgreSQL: In postgresql I used the following script.
do
$$
DECLARE
v_f1 float = '74.3658319091568';
v_f3 text;
BEGIN
SELECT regexp_replace(v_f1::varchar, '\s+$', '') INTO v_f3;
Raise info '%',v_f3;
END;
$$
--Output
INFO: 74.3658319091568
I didn't get the result as I get in the SQL Server.
You can try this way
do
$$
DECLARE
v_f1 float8 = '74.3658319091568';
v_f3 text;
BEGIN
SELECT to_char( v_f1, 'FM999999.0000') INTO v_f3;
Raise info '%',v_f3;
END;
$$
FM(prefix) -fill mode (suppress leading zeroes and padding blanks)
Using data type formatting
Your Postgres float is a synonym for real, which has 6 digits precision. In SQL Server a default float has 15 digits precision.
You could use a Postgres double precision which also has 15 digits precision. There is no SQL Server type that has 6 digits precision.
Note: you normally don't get any whitespace when converting a float to a text type. So replacing whitespace is useless (but also harmless.)
Note 2: in SQL Server, when using a fixed-length char, trailing spaces are removed. So REPLACE(#f1,CHAR(160),'') replaces an empty string with an empty string.
Related
Only found this related answer: Convert octal to decimal in SQL
Based on https://www.rapidtables.com/convert/number/octal-to-decimal.html?x=0325,
Octal: 0325 should convert to decimal 213.
The accepted answer from the SQL Server question can be converted to Postgres. It's actually a bit easier as you can split the string directly into the letters using string_to_table
create function octal_to_decimal(p_input text)
returns numeric
as
$$
select sum(x.digit::int * 8 ^ (length(p_input) - idx)) as val
from string_to_table(p_input, null) with ordinality as x(digit, idx)
$$
language sql
stable;
select octal_to_decimal('0325') returns 213
If you are on an older Postgres release, you need to replace string_to_table(p_input, null) with unnest(string_to_array(p_input, null))
I have postgresql function which accepts 4 arguments
CREATE OR REPLACE FUNCTION public.manual_table_parsing_monthly_custom_edits(
schema_name text,
main_permit text,
manual_table text,
permit_num text)
RETURNS void AS
$BODY$
DECLARE
e record;
load_move_count double precision;
BEGIN
EXECUTE format('Insert into %I.%I(permit_date,permit_number,year,month_number,
report_permit_date,job_category,address,legal_description,neighbourhood,neighbourhood_number,
job_description,work_type,floor_area,construction_value,zoning,units_added,
latitude,longitude,location,count,building_type,building_type_number,filter,community,
groups,plan,block,lot,unit_id,dwelling,condo_fh,developer,builder,unit_address,construction_type,geom)
select permit_date,permit_number,year,month_number,
report_permit_date,job_category,address,legal_description,neighbourhood,neighbourhood_number,
job_description,work_type,floor_area,construction_value,zoning,units_added,
latitude,longitude,location,count,building_type,building_type_number,filter,community,
groups,plan,block,lot,unit_id,dwelling,condo_fh,developer,builder,unit_address,construction_type,geom
from %I.%I
where flag like ''move'' or flag like ''load'' and permit_number
=%I',schema_name,main_permit,schema_name,manual_table,permit_number);
The last argument in a function permit_number which is used in the where statement is raising error no column 'yyyy'. Its because the %I is taking the value within double quotes. How should i edit so that the value will be within single quotes
As per documentiaion %I should be used for identifiers, and %L should be used for literal values.
Also should use $$ quoting, to ease reading of your function...
I have a function to left pad bit stings in PostgreSQL 9.5:
CREATE OR REPLACE FUNCTION lpad_bits(val bit varying)
RETURNS bit varying as
$BODY$
BEGIN return val::bit(32) >> (32-length(val));
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE;
which works fine:
# select lpad_bits(b'1001100111000');
lpad_bits
----------------------------------
00000000000000000001001100111000
(1 row)
My problem is when I try to add a parameter to change the amount of padding:
CREATE OR REPLACE FUNCTION lpad_bits(val bit varying, sz integer default 1024)
RETURNS bit varying as
$BODY$
BEGIN return val::bit(sz) >> (sz-length(val));
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE;
The function is now broken:
# select lpad_bits(b'1001100111000', 32);
ERROR: invalid input syntax for integer: "sz"
LINE 1: SELECT val::bit(sz) >> (sz-length(val))
^
QUERY: SELECT val::bit(sz) >> (sz-length(val))
CONTEXT: PL/pgSQL function lpad_bits(bit varying,integer) line 2 at RETURN
I have stared at the bitstring documentation and PL/pgSQL function documentation, am simply not seeing what is fundamentally different between these two implementations.
Why?
PL/pgSQL executes SQL queries like prepared statements. The manual about parameter substituion:
Prepared statements can take parameters: values that are substituted
into the statement when it is executed.
Note the term values. Only actual values can be parameterized, but not key words, identifiers or type names. 32 in bit(32) looks like a value, but the modifier of a data type is only a "value" internally and can't be parameterized. SQL demands to know data types at planning stage, it cannot wait for the execution stage.
You could achieve your goal with dynamic SQL and EXECUTE. As proof of concept:
CREATE OR REPLACE FUNCTION lpad_bits(val varbit, sz int = 32, OUT outval varbit) AS
$func$
BEGIN
EXECUTE format('SELECT $1::bit(%s) >> $2', sz) -- literal
USING val, sz - length(val) -- values
INTO outval;
END
$func$ LANGUAGE plpgsql IMMUTABLE;
Call:
SELECT lpad_bits(b'1001100111000', 32);
Note the distinction between sz being used as literal to build the statement and its second occurrence where it's used as value, that can be passed as parameter.
Faster alternatives
A superior solution for this particular task is to just use lpad() like #Abelisto suggested:
CREATE OR REPLACE FUNCTION lpad_bits2(val varbit, sz int = 32)
RETURNS varbit AS
$func$
SELECT lpad(val::text, sz, '0')::varbit;
$func$ LANGUAGE sql IMMUTABLE;
(Simpler as plain SQL function, which also allows function inlining in the context of outer queries.)
Several times faster than the above function. A minor flaw: we have to cast to text and back to varbit. Unfortunately, lpad() is not currently implemented for varbit. The manual:
The following SQL-standard functions work on bit strings as well as
character strings: length, bit_length, octet_length, position, substring, overlay.
overlay() is available, we can have a cheaper function:
CREATE OR REPLACE FUNCTION lpad_bits3(val varbit, base varbit = '00000000000000000000000000000000')
RETURNS varbit AS
$func$
SELECT overlay(base PLACING val FROM bit_length(base) - bit_length(val))
$func$ LANGUAGE sql IMMUTABLE;
Faster if you can work with varbit values to begin with. (The advantage is (partly) voided, if you have to cast text to varbit anyway.)
Call:
SELECT lpad_bits3(b'1001100111000', '00000000000000000000000000000000');
SELECT lpad_bits3(b'1001100111000', repeat('0', 32)::varbit);
We might overlaod the function with a variant taking an integer to generate base itself:
CREATE OR REPLACE FUNCTION lpad_bits3(val varbit, sz int = 32)
RETURNS varbit AS
$func$
SELECT overlay(repeat('0', sz)::varbit PLACING val FROM sz - bit_length(val))
$func$ LANGUAGE sql IMMUTABLE;
Call:
SELECT lpad_bits3(b'1001100111000', 32;
Related:
Postgresql Convert bit varying to integer
Convert hex in text representation to decimal number
The parser does not allow a variable at that place. The alternative is to use a constant and trim it:
select right((val::bit(128) >> (128 -length(val)))::text, sz)::bit(sz)
from (values (b'1001100111000', 32)) s(val,sz)
;
right
----------------------------------
00000000000000000001001100111000
Or the lpad function as suggested in the comments.
I have a float which between 0 and 1, e.g 0.342 or 0.34, etc. I need this formatted like so: .XXX, always three digits precision (with trailing zeroes) and never a leading zero (prior to the decimal. I have this:
CREATE OR REPLACE FUNCTION format_float(real) RETURNS text AS
$BODY$
BEGIN
return to_char($1, '9.999');
END;
$BODY$
LANGUAGE plpgsql VOLATILE COST 100;
But it pads the value with leading spaces. How can I get this working? I have tried '.999' in the to_char call but that doesn't work either, yielding .###
Would simple cast to an arbitrary precision number work for you?
SELECT 0.3456::numeric(4,3);
Same inside a function (btw, better use SQL functions, as optimizer can inline them):
CREATE FUNCTION ff(float) RETURNS numeric(4,3) AS $ff$
SELECT $1::numeric(4,3);
$ff$ LANGUAGE sql;
I have a PostgreSQL table that I want to alter a column from bigint to bytea byte to hold more data. I am thinking using the following sequence:
alter table mytable add new_column
update mytable set new_column = int8send(old_column)
alter table drop old_column
alter table rename new_column to old_column
The above sequence works, the only problem is that I want the byte sequence in the bytea to be reversed. For example, if a value in old_column is 0x1234567890abcdef, the above sequence would generate \0224Vx\220\253\315\357, but I want it to be
\357\315\253\220xV4\022. Seems like the resulting bytea uses the big-endian order from originating bigint.
Is there an easy way to do that without writing a program? I was looking for a swap64() sort of function in PostgreSQL but failed to find one.
Here's a pure-SQL function I wrote to reverse the byte-order of a bytea-type value:
CREATE OR REPLACE FUNCTION reverse_bytes_iter(bytes bytea, length int, midpoint int, index int)
RETURNS bytea AS
$$
SELECT CASE WHEN index >= midpoint THEN bytes ELSE
reverse_bytes_iter(
set_byte(
set_byte(bytes, index, get_byte(bytes, length-index)),
length-index, get_byte(bytes, index)
),
length, midpoint, index + 1
)
END;
$$ LANGUAGE SQL IMMUTABLE;
CREATE OR REPLACE FUNCTION reverse_bytes(bytes bytea) RETURNS bytea AS
'SELECT reverse_bytes_iter(bytes, octet_length(bytes)-1, octet_length(bytes)/2, 0)'
LANGUAGE SQL IMMUTABLE;
I just wrote it yesterday, so it's not particularly well-tested nor optimized, but it seems to work, at least on byte strings up to 1k in length.
It is possible to byte-swap without plpgsql code using regexp extractions on the hexadecimal representation.
Here's an example to swap a bigint constant, assuming SET standard_conforming_strings to ON (the default with PG 9.1)
select regexp_replace( lpad(to_hex(x'123456789abcd'::bigint),16,'0'),
'(\w\w)(\w\w)(\w\w)(\w\w)(\w\w)(\w\w)(\w\w)(\w\w)',
'\8\7\6\5\4\3\2\1');
It returns cdab896745230100. Then apply decode(value, 'hex') to convert that to a bytea.
The whole type conversion could actually be done in a single SQL statement:
ALTER TABLE mytable ALTER COLUMN old_column TYPE bytea
USING decode(
regexp_replace( lpad(to_hex(old_column), 16,'0'),
'(\w\w)(\w\w)(\w\w)(\w\w)(\w\w)(\w\w)(\w\w)(\w\w)',
'\8\7\6\5\4\3\2\1')
, 'hex');
I am playing with pageinspect module now, and I was also curios how to change byte order of an existing bytea value, which pretty much matches your case.
I've come up with the following function:
CREATE OR REPLACE FUNCTION reverse(bytea) RETURNS bytea AS $reverse$
SELECT string_agg(byte,''::bytea)
FROM (
SELECT substr($1,i,1) byte
FROM generate_series(length($1),1,-1) i) s
$reverse$ LANGUAGE sql;
It's pretty straightforward and works similar to textual reverse() function:
WITH v(val) AS (
VALUES ('\xaabbccdd'::bytea),('\x0123456789abcd'::bytea)
)
SELECT val, reverse(val)
FROM v;
This function, while not exactly what you're looking for, should help you get on your way.
The source code from that function is reproduced verbatim below.
CREATE OR REPLACE FUNCTION utils.int_littleendian(v_number integer)
RETURNS bytea AS
$BODY$
DECLARE
v_textresult bytea;
v_temp int;
v_int int;
v_i int = 0;
BEGIN
v_int = v_number;
v_textresult = '1234';
WHILE(v_i < 4) LOOP
raise notice 'loop %',v_int;
v_temp := v_int%256;
v_int := v_int - v_temp;
v_int := v_int / 256;
SELECT set_byte(v_textresult,v_i,v_temp) INTO v_textresult;
v_i := v_i + 1;
END LOOP;
return v_textresult;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;