I am working on a data upgrade issue.
A new column has been added to our Existing DB2 table.
In order to upgrade Client's DB2 table, I am unloading the data from the existing DB2 table with a constant value for the new column(lets say D of type SMALLINT) as shown below:
UNLOAD TABLESPACE XYZ.ABC
DELIMITED COLDEL X'2C' CHARDEL X'22'
PUNCHDDN SYSPUN01
UNLDDN SYSREC01 CCSID(367)
FROM TABLE DB2BG111.table_name
(
A POSITION(*) CHAR(2)
, B POSITION(*) SMALLINT
, C POSITION(*) CHAR(4)
, D (new column) CONSTANT X'0000'
)
While unloading the data, we are using following unload parameters:
X'2C': Column Delimiter
X'22': Character Delimiter
CCSID(367): EBCDIC to ASCII conversion
Problem tham I am facing is, DB2 is adding character delimiter X'22' after the value of the column D in the unload record.
Please note column B is an existing column and is declared as SMALLINT, DB2 not adding character del for this in the unload record.
This may be happening because new column D added here is not declared as a SMALLINT and hence it is not treated like an SMALLINT and DB2 is ending a char del for this in the unload record.
I am just looking for a way to get out of this situation, i do not want my new column D to be character delimited in the unload record.
Any suggestions to overcome this would be highly appreciated.
One option would be to use DSNTIAUL to perform the unload, and select the constant in the select list.
SELECT A, B, C, CAST (0 AS SMALLINT) AS D
FROM TABLE DB2BG111.table_name;
Best regards,
Patrick Bossman
Related
I have a task to create a Liquibase migration to change a value affext in table trp_order_sold, which is right now int8, to varchar (or any other text type if it's more likely to be possible).
The script I made is following:
ALTER TABLE public.trp_order_sold
ALTER COLUMN affext SET DATA TYPE VARCHAR
USING affext::varchar;
I expected that USING affext::text; part is gonna work as a converter, however with or without it I am getting this error:
ERROR: operator does not exist: varchar >= integer
Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
Any hints on what I'm doing wrong? Also I am writing a PostgreSQL script but a working XML equivalent would be fine for me as well.
These would most typically use or depend on your column:
a generated column
a trigger
a trigger's when condition
a view or a rule
a check constraint
In my test (online demo) only the last one leads to the error you showed:
create table test_table(col1 int);
--CREATE TABLE
alter table test_table add constraint test_constraint check (col1 >= 1);
--ALTER TABLE
alter table test_table alter column col1 type text using col1::text;
--ERROR: operator does not exist: text >= integer
--HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
You'll have to check the constraints on your table with \d+ command in psql, or by querying the system tables:
SELECT con.*
FROM pg_catalog.pg_constraint con
INNER JOIN pg_catalog.pg_class rel
ON rel.oid = con.conrelid
INNER JOIN pg_catalog.pg_namespace nsp
ON nsp.oid = connamespace
WHERE nsp.nspname = 'your_table_schema'
AND rel.relname = 'your_table_name';
Then you will need to drop the constraint causing the problem and build a new one to work with your new data type.
Since integer 20 goes before integer 100, but text '20' goes after text '100', if you plan to keep the old ordering behaviour you'd need this type of cast:
case when affext<0 then '-' else '0' end||lpad(ltrim(affext::text,'-'),10,'0')
and then make sure new incoming affext values are cast accordingly in an insert and update trigger. Or use a numeric ICU collation similar to this.
I have HEX data like this (F9F9F9F9) returned from a query. When I checked from IBM link :
https://www.ibm.com/support/knowledgecenter/en/SS2MB5_14.1.0/com.ibm.xlf141.bg.doc/language_ref/asciit.html
F9 = 9 and F9 = 9
Here I should get result as 9999
I jhave around 1000 hex records like this in a table.
How can I convert this hex values to it corrsponding EBCDIC ?
I tried like :
select cast(col char(2) as codebase(37)) from table
How ever, its not working.
THis link is also not working: I'm not sure if its a cobol code or DB2 script. : http://www.ibmmainframeforum.com/db2/topic8785.html
Please help.Thanks.
select cast(col char(2) as codebase(37)) from table
Correct Syntax.
select cast(col as char(2) ccsid 37) as col from table
Generally you don't want to do this over and over so maybe just alter the table.
ALTER TABLE mylib/Z1 ALTER COLUMN JOJOB SET DATA TYPE CHARACTER (
10) CCSID 37 NOT NULL WITH DEFAULT
Or create a view over the table for read only data and read from the view.
create view tablev as
select cast(col as char(2) ccsid 37) as col from table
After reading the following link..
https://dba.stackexchange.com/questions/94443/how-should-a-numeric-value-that-is-an-external-key-be-stored
I decided to alter a column from text to:
int(9) UNSIGNED ZEROFILL NOT NULL
However, I am not sure of the SQL statement to use. I know the below is not correct because it does not include the the 9 digits, unsigned zerofill and not NULL parameters.
ALTER TABLE "Organizations" ALTER COLUMN "EIN" TYPE INTEGER using "EIN"::INTEGER
UPDATE:
Since Postgres does not use zerofill or INT(9). What would be the recommended data type of an EIN number that is 9 digits?
I would recommend below as is in two statements:
ALTER TABLE "Organizations" ALTER COLUMN "EIN" TYPE INTEGER using "EIN"::INTEGER;
ALTER TABLE "Organizations" ALTER COLUMN "EIN" SET NOT NULL;
decoration with padding zeros can be done on select with client (or rule, which would be effectively just a view, selected instead, and thus I think overcomplicating here - ((and changing to int to select text with zeroes - does not sound reasonambe))), eg:
t=# select lpad(123::int::text,9,'0');
lpad
-----------
000000123
(1 row)
so If its needed, can be mocked up
For the 9-digit restriction, a domain over int can work:
CREATE DOMAIN ein AS int CHECK (VALUE>0 AND VALUE<1000000000);
Then ein can be used in declarations as a type, for instance:
=> CREATE TABLE test(id ein, t text);
CREATE TABLE
=> insert into test values(2*1e9::int);
ERROR: value for domain ein violates check constraint "ein_check"
=> insert into test values(100);
INSERT 0 1
The zerofill bit is different, it's about presentation, not storage,
and that part cannot be specialized for a domain.
You may instead apply to_char to the values, for example:
=> select to_char(id,'000000000') from test;
to_char
------------
000000100
and possibly access this through a stored view or a presentation
function that takes only the ein as argument
if you prefer to abstract this from the client.
To go further, you could create a full type with CREATE TYPE
backed with C code for the INPUT and OUTPUT function, and these functions could implement the 9-digit left-padded format as the input/output format, so that the user may never see anything else at the SQL level.
I want to get records from my local txt file to postgresql table.
I have created following table.
create table player_info
(
Name varchar(20),
City varchar(30),
State varchar(30),
DateOfTour date,
pay numeric(5),
flag char
)
And, my local txt file contains following data.
John|Mumbai| |20170203|55555|Y
David|Mumbai| |20170305| |N
Romcy|Mumbai| |20170405|55555|N
Gotry|Mumbai| |20170708| |Y
I am just executing this,
copy player_info (Name,
City,
State,
DateOfTour,
pay_id,
flag)
from local 'D:\sample_player_info.txt'
delimiter '|' null as ''
exceptions 'D:\Logs\player_info'
What I want is,
For my numeric column, If 3 spaces are there,
then I have to insert NULL as pay else whatever 5 digits numeric number.
pay is a column in my table whose datatype is numeric.
Is this correct or possible to do this ?
You cannot store strings in a numeric column, at all. 3 spaces is a string, so it cannot be stored in the column pay as that is defined as numeric.
A common approach to this conundrum is to create a staging table which uses less precise data types in the column definitions. Import the source data into the staging table. Then process that data so that it can be reliably added to the final table. e.g. in the staging table set a column called pay_str to NULL where pay_str = ' ' (or perhaps LIKE ' %')
I have a table with more than 30.000 entries and have to add a new column (zip_prefixes) containing the first digit of the a zip code (zcta).
I created the column successfully:
alter table zeta add column zip_prefixes text;
Then I tried to put the values in the column with:
update zeta
set zip_prefixes = (
select substr(cast (zctea as text)1,1)
from zeta)
)
Of course I got:
error more than one row returned by a subquery used as an expression
How can I get the first digit of the value from zctea into column zip_prefixes of the same row?
No need for sub-select:
update zeta
set zip_prefixes = substr(zctea, 1, 1);
update zeta
set zip_prefixes = substr(zctea as text)1,1)
There is no need for select query and casting
Consider not adding a functionally dependent column. It's typically cleaner and cheaper overall to retrieve the first character on the fly. If you need a "table", I suggest to add a VIEW.
Why the need to cast(zctea as text)? A zip code should be text to begin with.
Name it zip_prefix, not zip_prefixes.
Use the simpler and cheaper left():
CREATE VIEW zeta_plus AS
SELECT *, left(zctea::text, 1) AS zip_prefix FROM zeta; -- or without cast?
If you need the additional column in the table and the first character is guaranteed to be an ASCII character, consider the data type "char" (with double quotes). 1 byte instead of 2 (on disk) or 5 (in RAM). Details:
What is the overhead for varchar(n)?
Any downsides of using data type "text" for storing strings?
And run both commands in one transaction if you need to minimize lock time and / or avoid a visible column with missing values in the meantime. Faster, too.
BEGIN;
ALTER TABLE zeta ADD COLUMN zip_prefix "char";
UPDATE zeta SET zip_prefixes = left(zctea::text, 1);
COMMIT;