SystemVerilog dist constraint - constraints

I'm missing something in how to setup a dist constraint. I'm trying to get an equal weight between two ranges [0:31] and [32:65535]. I've set up a simple test:
class data;
rand bit [15:0] field1;
constraint c_f1 { field1 dist {[0:31] := 1, [32:65535] := 1};}
endclass
module testbench;
initial begin
data test_h;
test_h = new();
repeat(10) begin
assert(test_h.randomize());
$display("field1 = %h", test_h.field1);
end
end
endmodule
However, I'm seeing most values > 32. What have I misunderstood here?

Use the :/ operator instead of the := operator. Change:
constraint c_f1 { field1 dist {[0:31] := 1, [32:65535] := 1};}
to:
constraint c_f1 { field1 dist {[0:31] :/ 1, [32:65535] :/ 1};}
Refer to IEEE Std 1800-2017, section 18.5.4 Distribution.
The :/ operator assigns the specified weight to the item or, if the
item is a range, to the range as a whole. If there are n values in the
range, the weight of each value is range_weight / n .
This gives more values between 0-31:
field1 = 0012
field1 = 001f
field1 = 000f
field1 = a138
field1 = 0018
field1 = 001c
field1 = 9d48
field1 = 0009
field1 = 85bf
field1 = f930

Related

substr instr length for loop

good morning guys i have a problem with code i work on Health Care and complain code must be checkbox but they ask for Report that contain the treatment code which is gonna appear in database like this 1:15:2:3 etc so i need to calculate each code separate
i have to count until i get ":" then i need to take the number which can be 1 or 2 digit then making inner join with the other table
can anyone help me to fix this function and the problem in the loop and get the number for each one
create or replace function hcc_get_tcd_codes (p_id in number )
return varchar2 is
x number := 0 ;
y number := 0 ;
z number ;
code1 number ;
code_name varchar2(15);
begin
for i in 0 .. x
loop
select length(t.tcd_codes ) into x from hcc_patient_sheet t where t.id = p_id ; --- (9)العدد كامل
select instr(tcd_codes, ':') into y from hcc_patient_sheet t where t.id = p_id ; ---- عدد الكود الاو(3)ل
select instr(tcd_codes, ':')+1 + y into z from hcc_patient_sheet t where t.id = p_id ; --عدد الكود كامل +1
enter code here
i := x -y ;
select substr(t.tcd_codes,z, instr(tcd_codes, ':')-1) into code1
--,select substr(t.tcd_codes, 0, instr(tcd_codes, ':')-1) as code2
from Hcc_Patient_Sheet t
where t.id = 631 ;
select t.alt_name into code_name from hcc_complaint_codes t where t.code = code1 ;
select instr(tcd_codes, ':') into y from hcc_patient_sheet t where t.id = p_id ; ---- عدد الكود الاول
return code_name ;
end loop ;
end;
Often with frequent sounding string processing issues, a wheel has already been invented, and even packaged.
select * from table(apex_string.split('THIS:IS:GREAT',':'));
Partial SUBSTR doesn't seem to be the best option; I'd suggest you to split that colon-separated-values string into row as follows:
SQL> with test (col) as
2 (select '1:15:2:3' from dual)
3 select regexp_substr(col, '[^:]+', 1, level) one_value
4 from test
5 connect by level <= regexp_count(col, ':') + 1;
ONE_VALUE
--------------------------------
1
15
2
3
SQL>
and use such an option in your query; something like this:
select ...
into ...
from some_table t
where t.id in (select regexp_substr(that_string, '[^:]+', 1, level) one_value
from dual
connect by level <= regexp_count(that_string, ':') + 1
);
If it has to be row-by-row, use the above option as a source for the cursor FOR loop, as
for cur_r in (select regexp_substr(that_string, '[^:]+', 1, level) one_value
from dual
connect by level <= regexp_count(that_string, ':') + 1
)
loop
do_something_here
end loop;

Error PLSQL copying content of 2 tables in 1 with varray

I have this tables:
CREATE TABLE departments (
dep_na number(2) NOT NULL PRIMARY KEY,
dname VARCHAR2(15),
loc VARCHAR2(15)
);
INSERT INTO departments VALUES (20,'CONTABILITY','SEVILLA');
INSERT INTO departments VALUES (30,'INVEST','MADRID');
COMMIT;
CREATE TABLE employees (
emp_nu number(4) NOT NULL PRIMARY KEY,
surname VARCHAR2(10),
oficio VARCHAR2(10),
dir number(4),
date_a DATE ,
salar number(6,2),
comis number(6,2),
dep_na number(2) NOT NULL REFERENCES departments(dept_no)
);
ALTER SESSION SET NLS_DATE_FORMAT='DD/MM/YYYY';
INSERT INTO employees VALUES (7369,'SANCHEZ','EMPLEADO',7902,'17/12/1990',1040,NULL,20);
INSERT INTO employees VALUES (7499,'ARROYO','VENDEDOR',7698,'20/02/1990',1500,390,30);
COMMIT;
create or replace
TYPE TDEP AS OBJECT(
dep_na NUMBER(2),
dname VARCHAR2(15),
loc VARCHAR2(15)
);
CREATE OR REPLACE TYPE TEMPLE AS OBJECT(
emp_nu number(4),
surname VARCHAR2(10),
oficio VARCHAR2(10),
dir number(4),
date_a DATE,
salar number(6,2),
comision number(6,2),
dep_na TDEP
);
CREATE OR REPLACE TYPE VEMPLE AS VARRAY(20) OF TEMPLE;
I created the following table pack with varray and types, but I have the problem that when I insert the contents of the employees and departments tables in the table pack the computer gives me error.
CREATE TABLE pack(
array_employees VEMPLE,
departme TDEP
);
I have problems with this code:
DECLARE
T VEMPLE;
A TDEP
CURSOR C1 is select * from departamentos order by dep_na;
CURSOR C2(DEPAR NUMBER) is select * from empleados where dep_na = depar;
j integer := 1;
BEGIN
for i in C1 LOOP
DBMS_OUTPUT.PUT_LINE(i.dep_na);
T := NEW VEMPLE();
A := NEW TDEP();
j := 1;
for x in C2(i.dep_na) loop
if j < T.LIMIT THEN
DBMS_OUTPUT.PUT_LINE(x.apellido || ' - ' || i.dep_na);
T.extend;
T(j) := NEW TEMPLE(NULL, NULL, NULL, NULL);
T(j).departments := NEW TDEP(i.loc, NULL, NULL);
j := j + 1;
end if;
end loop;
INSERT INTO Grupos VALUES(i.A, T);
end loop;
end;
/
I need help with this query in Oracle. I have problems with the cursor.
The immediate problem is that you're just missing a semicolon after A TDEP in the declare section, which is causing your ORA-06550: line 4, column 1: PLS-00103: Encountered the symbol "CURSOR" when expecting ... error. Which you haven't shown, but you said it's a cursor error, so that seems to line up.
But you have lots of other errors, some from inconsistent naming which I think is from partially changing things for posting, but partly from how you're creating object instances. I think this is pretty much clean:
DECLARE
T VEMPLE;
A TDEP;
CURSOR C1 is select * from departments order by dep_na;
CURSOR C2(DEPAR NUMBER) is select * from employees where dep_na = depar;
j integer := 1;
BEGIN
for i in C1 LOOP
DBMS_OUTPUT.PUT_LINE(i.dep_na);
T := NEW VEMPLE();
-- supply values to constructor
A := NEW TDEP(i.dep_na, i.dname, i.loc);
j := 1;
for x in C2(i.dep_na) loop
if j < T.LIMIT THEN
DBMS_OUTPUT.PUT_LINE(x.surname|| ' - ' || i.dep_na);
T.extend;
-- supply values to constructor
T(j) := NEW TEMPLE(x.emp_nu, x.surname, x.oficio,
x.dir, x.date_a, x.salar, x.comis, A);
-- no idea what the next line is doing
-- T(j).departments := NEW TDEP(i.loc, NULL, NULL);
j := j + 1;
end if;
end loop;
-- elements were wrong way round, which wouldn't matter if you
-- included the column names - which is good practice anyway
INSERT INTO pack VALUES(T, A);
end loop;
end;
/
SQL Fiddle. (Don't try to select from the table in the Fiddle though, it struggles with object types; this just shows it doesn't error...)
I assume this is an exercise. There are probably better and more efficient ways to convert from a relational to an object schema.

How to convert the Long value to String using sql

I am doing a long to string conversion using java in following way.
Long longValue = 367L;
String str = Long.toString(longValue, 36).toUpperCase();
this is returning me as value A7. how can achieve this in doing oracle sql.
UPDATED:
Hi, I have analyzed how java code is working then wanted to implement the same thing in procedure.
First point is Input vaues. LONG and Radix. in my case Radix is 36. so i will have values from 1..9A...Z0 It picks up the values from this set only.
Second point Long value as input. we have to divide this value with radix. if the quotient is more than 36 again we need to divide.
For eaxmple 367 then my converted value is 10(quotient) 7(remainder) that is A7.
3672 converted value is 102 0 i need to do again for 102 that is 2 -6 so my final value will be 2-6 0 that is 2U0(- means reverse the order).
UPDATE 2:
Using oracle built in functions we can do this. this was solved by my friend and gave me a function.I want to thank my friend. this will give me an out put as follows.
367 then my converted value is 10(quotient) 7(remainder) that is *A*7.(I modified this to my requirement).
FUNCTION ENCODE_STRING(BASE_STRING IN VARCHAR2,
FROM_BASE IN NUMBER,
TO_BASE IN NUMBER)
RETURN VARCHAR2
IS
V_ENCODED_STRING VARCHAR(100);
BEGIN
WITH N1 AS (
SELECT SUM((CASE
WHEN C BETWEEN '0' AND '9'
THEN TO_NUMBER(C)
ELSE
ASCII(C) - ASCII('A') + 10
END) * POWER(FROM_BASE, LEN - RN)
) AS THE_NUM
FROM (SELECT SUBSTR(BASE_STRING, ROWNUM, 1) C, LENGTH(BASE_STRING) LEN, ROWNUM RN
FROM DUAL
CONNECT BY ROWNUM <= LENGTH(BASE_STRING))
),
N2 AS (
SELECT (CASE
WHEN N < 10
THEN TO_CHAR(N)
ELSE CHR(ASCII('A') + N - 10)
END) AS DIGI, RN
FROM (SELECT MOD(TRUNC(THE_NUM/POWER(TO_BASE, ROWNUM - 1)), TO_BASE) N, ROWNUM RN
FROM N1
CONNECT BY ROWNUM <= TRUNC(LOG(TO_BASE, THE_NUM)) + 1)
)
SELECT SYS_CONNECT_BY_PATH(DIGI, '*') INTO V_ENCODED_STRING
FROM N2
WHERE RN = 1
START WITH RN = (SELECT MAX(RN) FROM N2)
CONNECT BY RN = PRIOR RN - 1;
RETURN V_ENCODED_STRING;
IN PL/SQL (or Oracle SQL) you have the a function called TO_CHAR.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions181.htm
It is not possible to do it in the pure SQL. You have to use PL/SQL.
Simple example how to do it PL/SQL:
CREATE TABLE long_tbl
(
long_col LONG
);
INSERT INTO long_tbl VALUES('How to convert the Long value to String using sql');
DECLARE
l_varchar VARCHAR2(32767);
BEGIN
SELECT long_col
INTO l_varchar
FROM long_tbl;
DBMS_OUTPUT.PUT_LINE(l_varchar);
END;
-- How to convert the Long value to String using sql
There is TO_LOB function but it can only by used when you insert data into table.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions185.htm
You can apply this function only to a LONG or LONG RAW column, and
only in the select list of a subquery in an INSERT statement.
There is also other, more proper way to do it by using "dbms_sql.column_value_long" but this gets complicated (fetching of the LONG column and appending to the CLOB type.)
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_sql.htm#i1025399
(Oracle Database PL/SQL Packages and Types Reference)

How to cast varchar to int in sql

I have table called ExamInfo. In that table the column Sub1 is of the type VARCHAR(50). The Sub1 column contains numeric, null and non-numeric data.
I want to select from ExamInfo where the data in Sub1 is greater than 81.
Here is my query:
select *
from Exam
where cast(sub1 as int) > 81`.
But it fails to cast resulting in an error.
Since your column contains mixed information and the cast is applied to the whole column, you need to make sure you only attempt to cast actual numeric values:
select *
from Exam
where case when ISNUMERIC(sub1) =1
and CHARINDEX('.', sub1) = 0
and sub1 >= -2147483648
and sub1 <= 2147483647
then cast(sub1 as int)
else 0
end > 81
This is an example on how to do it in SQL Server.
There is one more point of attention in this query and that is "Globalization". The '.' we are checking for as decimal point is not everywhere used as decimal point. If you have a localized SQL Server you can grab the correct decimal separator by doing
DECLARE #decimal_separator char(1)
set #decimal_separator = SUBSTRING(CONVERT(CHAR(3), CONVERT(NUMERIC(2,1), 1.0/2)), 2, 1)
Which would turn the query into:
DECLARE #decimal_separator char(1)
set #decimal_separator = SUBSTRING(CONVERT(CHAR(3), CONVERT(NUMERIC(2,1), 1.0/2)), 2, 1)
select *
from Exam
where case when ISNUMERIC(sub1) =1
and CHARINDEX(#decimal_separator, sub1) = 0
and sub1 >= -2147483648
and sub1 <= 2147483647
then cast(sub1 as int)
else 0
end > 81
It looks like some of the data in sub1 cannot be cast as an int. Check the data for non numeric data.
Try this:
SELECT * FROM ExamInfo
WHERE CAST( (CASE
WHEN ISNUMERIC(Sub1) <> 1
THEN NULL
--Ignore any decimal value
WHEN ISNUMERIC(Sub1 + '.0e0') <> 1
THEN NULL
WHEN CAST(Sub1 AS NUMERIC(38, 0)) BETWEEN -2147483648 AND 2147483647
THEN Sub1
ELSE null
END) AS INT ) > 81;

Verify existence of two columns in different tables in a single SQL transaction

I'm trying to verify if data exists in two different tables in a single transaction. The reason for the single transaction is the database gets hit about 1-3 million times a day so adding anymore than 1 extra transaction would increase that number up to 9 million, and my poor little server needs a break :)
So I need to check if an ID exists in table X and table Y and return the results to my VB.net script so I can handle the outcome Ideally something like this would work
if exists (select id from X where id = #id)
print 'True,' else print 'False,'
if exists (select id from Y where id = #id)
print 'True' else print 'False'
Which gives me "True, True" if exists in both or "True, False" etc etc... But that only displays in SQL print and not actually returning it as an object/string or array values that I can use.
I'm open to any sort of solution of this nature that can give me two results from a single transaction and how to handle that response in vb. Thanks
SELECT
Case When EXISTS(SELECT 1 FROM X WHERE id = #id) Then 1 Else 0 End AS IsInX,
Case When EXISTS(SELECT 1 FROM Y WHERE id = #id) Then 1 Else 0 End AS IsInY
select (select COUNT(*) from X where id = #id) AS x_exists,
(select COUNT(*) from Y where id = #id) AS y_exists
This returns one data row with two fields, each containing either 0 or 1 (or more, if id is not unique).
CREATE PROCEDURE CheckIDOnTables(#ID int)
AS
BEGIN
DECLARE #X AS NVARCHAR(10)
DECLARE #Y AS NVARCHAR(10)
Set #X = 'False'
Set #Y = 'False'
if exists (select id from TableX where id = #ID)
Set #X = 'True'
if exists (select id from TableY where id = #ID)
Set #Y = 'True'
SELECT #X AS XExists, #Y AS YEsists
END
It will give you your desired results.

Resources