#!/usr/bin/perl
###############################################################################
# Program : ruleCheck.pl 根据规则组,检查规则组的通过率
# Scrpition: 执行本数据字段批量检查需要以下几个步骤
# 1.查询出所有的规则组,进行第一次循环
# 2.查询当前规则组下的所有规则(一般都是针对同一个字段),循环
# 每一个规则,从中提取规则sql
# 3.一组规则的每个规则都会在前一个规则的执行基础之上计算通过率,
# 有效检查记录总数,计算的粒度细分到机构,规则编号
# Writer : zengst
# Version :
###############################################################################
use strict;#对语法做严格限制,如变量必须先用my声明
use DBI;
use Time::Local;
my $dbh;#与数据库的连接
my $USER; #登录用户名
my $PASSWD; #登录口令
my $RUN_DATE;#质量检测日期
my $Topic_Area;#检查的专题
my $Sys_Id;#检查的系统id
my $Map_Id;#规则组id
my $table_Name;#检查的表名
my $Check_Column_Name;#检查的字段名称,一个规则组,检测一个字段
my $PK_Column_Name;#检查的表的主键字段
my $Org_Column_Name;#机构字段名称,注意不是值,因为检查的业务系统的机构字段可能不一致
my $Rule_Name;#规则说明,即检查的是什么
my $checkID; #检查编号
my $SQLClause;#当前规则检查的sql
my $RuleTable='EASTDQM.Rule';#规则信息表
my $RuleGroupTable='EASTDQM.RuleGroup';#规则组信息表
my $Rule_Info;#规则信息
my $Rule_Group;#规则组信息
my $check_Result = 'EASTDQM.Check_Result';#轻度结果汇总表
my $check_detail='EASTDQM.Check_Result_Detail';#检查结果明细表
my $RUNDATE=GetNowDate();#质量检查日期
my $modifydate;
my $CheckDimension;#规则维度
my $CheckSegmentation;#
my $Org_Id;#机构号
my $logFile;
my $check_detail_sample = 'EASTDQM.check_detail_sample';
my $ORG_CHK='ORG_CHK';#防止同一个NBJGH字段在select列出现多次时引发问题
my $job_params = $ARGV[0]; #传入参数
my $JOB = substr($job_params,8,length($job_params)-21);#获得表名。
my $TX_DATE=substr($job_params,length($job_params)-12,8);#数据日期
my $parallelTable = substr($job_params,4,4);
my $parallelColumn = substr($job_params,4,4);
my $whereClause;
if ($job_params == '' ){
print (GetNowTime() . " please input the params that requird !\n");
return 1;
}
#日志文件目录
#一个大于号,表示覆盖原有文件的内容
#两个大于号表示在原有文件内容之后添加
my $lfnowtime =GetNowTimeNospechar();
open $logFile,">checkLog$lfnowtime.txt";
select $logFile;
$|=1;
#初始化数据库的连接信息
sub DBconnect{
$dbh = DBI->connect("dbi:ODBC:ahnxods", "odsuser", "ytods",{RaiseError => 1, AutoCommit => 0 })
|| die "Couldn't connect to database: ".DBI->errstr;
print $logFile (GetNowTime()." get connection success! \n ");
return $dbh;
}
##得到创建临时表的DDL,临时表是session级别的
#sub createtemptableDDL{
#my $createDDL = "create table ${check_detail_temp} as (select * from ${check_detail}) definition only ";
#return $createDDL;
#}
#得到规则组信息。因为每一个规则组里面的规则需要进行单独的
#权重评分,一次性搜索全部的规则时处理逻辑会相当复杂
sub getRuleGroupInfo{
#得到所有正在运行的规则组
my $groupInfoSQL = "select Map_Id,Topic_Area from ${RuleGroupTable} where Status= 1 and Table_Name=${parallelTable} and Check_Column_Name=${parallelColumn} order by Map_Id";
#my $groupInfoSQL = "select Map_Id,Topic_Area from ${RuleGroupTable} where Status= 1 and map_id in (select map_id from EASTDQM.RULE_UPDATE_ADV)";
#my $groupInfoSQL = "select Map_Id,Topic_Area from ${RuleGroupTable} where Status= 1 and map_id in ( select map_id from eastdqm.rule where check_id in ('4012','4013','4014','4025','4026','4027','9007','9013','9015','9023','3072',,'3106')) order by Map_Id";
my $sth = $dbh->prepare($groupInfoSQL) or return -1;
my $ret = $sth->execute() or return -1;
${Rule_Group} = $sth->fetchall_arrayref();
$sth->finish();
return ${Rule_Group};
}
#得到数据库配置表的信息
sub getRuleInfo{
my ($groupId)=@_;#参数传入规则组Map_id
my $ruleConfigSql =
"select check_id,Topic_Area,r.sys_id,r.table_Name,r.Check_Column_Name,".
"r.PK_Column_Name,r.Org_Column_Name,rule_name,modifydate,r.SQLClause,map_id,WhereClause ".
"from ${RuleTable} r".
" where r.status='1' and map_id=$groupId ".
" order by Rule_Prior asc";
my $sth = $dbh->prepare($ruleConfigSql) or return -1;
my $ret = $sth->execute() or return -1;
${Rule_Info} = $sth->fetchall_arrayref();
$sth->finish();
return 0;
}
#执行规则SQL
sub exeRuleSql{
#存储已经排好序的待执行的规则sql
my @exeCheckSql=();
for my $i(0..$#${Rule_Info}){
$checkID=${Rule_Info}->[$i]->[0]; #检查编号
print $logFile (GetNowTime()." Begin To Run Rule[$i]:$checkID \n");
$Topic_Area = ${Rule_Info}->[$i]->[1];#Rule_Info是一个二维数组,${Rule_Info}->[$i]表示是第i行
$Sys_Id=${Rule_Info}->[$i]->[2];
$table_Name=${Rule_Info}->[$i]->[3];
$Check_Column_Name=${Rule_Info}->[$i]->[4];
$PK_Column_Name=${Rule_Info}->[$i]->[5];
$Org_Column_Name=${Rule_Info}->[$i]->[6];
$Rule_Name=${Rule_Info}->[$i]->[7];
$modifydate=${Rule_Info}->[$i]->[8];
#$SQLClause=${Rule_Info}->[$i]->[9];
#$SQLClause =~ s/(\$[\w_]+)/eval $1/ge;
#$SQLClause =~ s/(\$\{[^\}]+\})/eval $1/ge;
$Map_Id=${Rule_Info}->[$i]->[10];
$whereClause = ${Rule_Info}->[$i]->[11];
$SQLClause = "select ${PK_Column_Name},${Org_Column_Name},${Check_Column_Name} from ${table_Name} where ${whereClause}";
push(@exeCheckSql,$SQLClause);
#为了防止多次执行,需要删除轻度汇总表和和检查明细表
#运行时要删除全部的机构数据
print $logFile (GetNowTime() . " **************************Clear The Result Table:**************************\n");
my $DelSql = "Delete From ${check_Result} Where Check_ID = ${checkID} and rundate='${RUNDATE}'";
my $sth = $dbh->prepare($DelSql) or return -1;
#返回影响的行数,select也可以影响行数
my $ret = $sth->execute() or return -1;
$sth->finish();
print $logFile (GetNowTime() . " **************************Clear The Result Table:Succeed[Rows:$ret] **************************\n");
print $logFile (GetNowTime() . " **************************Clear The Detail Table:**************************\n");
#todo 需要加上运行日期的校验 And RUNDATE = Cast('${RUNDATE}' As Date Format 'YYYYMMDD')
my $DelSql = "Delete From ${check_detail} Where Check_ID = ${checkID} and RUNDATE='${RUNDATE}'";
$sth = $dbh->prepare($DelSql) or return -1;
#返回影响的行数,也包括select语句
$ret = $sth->execute() or return -1;
$sth->finish();#释放结果集
print $logFile (GetNowTime() . " **************************Clear The Detail Table:Succeed[Rows:$ret]**************************\n");
#字符串的相等是eq,第一次执行的规则的记录总数是待检测表的记录总数
if($i==0){
my $fromposi = index($SQLClause,'FROM');
my $fromclause = substr($SQLClause,$fromposi+4);
#主键字段是多列,这里将它拼成一列
my $pkselect = '';
my @PKcon = split(",",$PK_Column_Name);
my $PKlen = $#PKcon;#获得数组的下标,数组为空时,返回-1
if($PKlen eq 0){
$pkselect = $PK_Column_Name;
}else{
foreach my $k(0..$PKlen){
if($k eq 0){
$pkselect = @PKcon->[$k];
}else{
$pkselect = $pkselect.'||'.'\'#\''.'||'.(@PKcon->[$k]);
}
}
}
#对检查的字段是多列情况的处理,将多列的数据拼接成一列
my $ckselect= '';
my @CKcon = split(",",$Check_Column_Name);
my $CKlen = $#CKcon;
if($CKlen eq 0){
$ckselect = $Check_Column_Name;
}else{
foreach my $k(0..$CKlen){
if($k eq 0){
$ckselect = @CKcon->[$k];
}else{
$ckselect = $ckselect.'||'.'\'#\''.'||'.(@CKcon->[$k]);
}
}
}
print $logFile (GetNowTime() ." ************************** insert into detail begin **************************\n");
#将规则sql的检查结果插入临时表,临时表表结构和detail表是完全一致的
my $detailinsertSql = "Insert Into ${check_detail}" .
" select ${checkID},'${RUNDATE}', ${Map_Id}," .
" '${Topic_Area}','${Sys_Id}','${table_Name}','${Check_Column_Name}','${CheckDimension}','${CheckSegmentation}',".
" ${pkselect},${Org_Column_Name},${ckselect} from ".$fromclause;
my $detailsth = $dbh->prepare($detailinsertSql) or return -1;
$detailsth->execute() or return -1;
$detailsth->finish();
print $logFile (GetNowTime() ." ************************** insert into detail end **************************\n");
print $logFile (GetNowTime() ." ************************** insert into sample data begin **************************\n");
#从全量表按照规则、机构和运行日期的维度取得样本数据,插入到样例表
#partition by 可以是多个字段
my $sampInsert = "insert into ${check_detail_sample}".
" select ${checkID},'${RUNDATE}',${Map_Id},'${Topic_Area}','${Sys_Id}','${table_Name}','${Check_Column_Name}',".
"'${CheckDimension}','${CheckSegmentation}',pk_column_value,org_id,check_column_value from ".
"(select crt.*,ROW_NUMBER() over( partition by org_id,check_id) as seq from ${check_detail} crt where rundate='${RUNDATE}') detailtmp ".
" where detailtmp.seq<6";
my $inssth = $dbh->prepare($sampInsert) or return -1;
$inssth->execute() or return -1;
$inssth->finish();
print $logFile (GetNowTime() ." ************************** insert into sample data end **************************\n");
print $logFile (GetNowTime() ." ************************** begin insert check_result**************************\n");
#将样本数据插入到result表,直接通过sql进行数据的循环插入,方式insert into table select ******
my $InsSql = " Insert Into ${check_Result}".
" select ${checkID},'${RUNDATE}', '${Rule_Name}',${Map_Id},'${Topic_Area}','${Sys_Id}','${table_Name}','${Check_Column_Name}','${CheckDimension}','${CheckSegmentation}',".
" mainorg ,effectCount,effectCount-decode(FailCount,null,0,FailCount), decode(FailCount,null,0,FailCount),".
" cast(decode(FailCount,null,0,FailCount) as double)/effectCount,cast((effectCount-decode(FailCount,null,0,FailCount)) as double)/effectCount from ".
"(select count(*) as effectCount, $Org_Column_Name as mainorg from ${table_Name} group by ${Org_Column_Name}) tmain ".
" left join ".
"(select count(*) as FailCount, org_id,check_id from ${check_detail} detail where detail.rundate = '${RUNDATE}'and check_id=${checkID} group by org_id,check_id) tdetail".
" on tmain.mainorg = tdetail.org_id";
my $collsth = $dbh->prepare($InsSql) or return -1;
$collsth->execute() or return -1;
$collsth->finish();
print $logFile (GetNowTime() ." ************************** end insert check_result**************************\n");
$dbh->commit();
#没有commit时,就不会插入到数据库
}else{
#上一次执行的sql,一个规则组下的第n个规则执行时,检查的有效记录数=全表-前面n-1次检查出的记录数
my $preWhereCluse = '';
my $arrIndex = $#exeCheckSql;
#当前是第i个规则sql,那么需要得到前面i-1个规则sql检测的sql
for(my $j=0;$j<=($arrIndex-1);$j++){
#这里要求规则sql都是有where条件的,截取的都是where之后的内容
#这里要求执行的规则sql只有where子句
my $whereposi = index(@exeCheckSql[$j],'WHERE');
my $whereclause = substr(@exeCheckSql[$j],$whereposi+5);
if($j eq 0){
$preWhereCluse = ' and not('.$whereclause.')';
}else{
$preWhereCluse = $preWhereCluse.' and not('.$whereclause.')';
}
}
#得到上一次规则sql的PK值,另外 select a ,b,b from (a,b,b,c) ... 这样的语句还是存在字段歧义的问题,并不是按照顺序来匹配数据的
#本次检查在上一次检查的基础上,排除上次规则检查有问题的记录
#因为PK可能是多个列,所以一定要加上括号,表示PK是一个整体一起使用的
my $currSqlCluse = $SQLClause.$preWhereCluse;
my $fromposi = index($currSqlCluse,'FROM');
my $fromclause = substr($currSqlCluse,$fromposi+4);
my $pkselect = '';
my @PKcon = split(",",$PK_Column_Name);
my $PKlen = $#PKcon;#获得数组的下标,数组为空时,返回-1
if($PKlen eq 0){
$pkselect = $PK_Column_Name;
}else{
foreach my $k(0..$PKlen){
if($k eq 0){
$pkselect = @PKcon->[$k];
}else{
$pkselect = $pkselect.'||'.'\'#\''.'||'.(@PKcon->[$k]);
}
}
}
my $ckselect= '';
my @CKcon = split(",",$Check_Column_Name);
my $CKlen = $#CKcon;
if($CKlen eq 0){
$ckselect = $Check_Column_Name;
}else{
foreach my $k(0..$CKlen){
if($k eq 0){
$ckselect = @CKcon->[$k];
}else{
$ckselect = $ckselect.'||'.'\'#\''.'||'.(@CKcon->[$k]);
}
}
}
print $logFile (GetNowTime() ." ************************** insert into detail begin **************************\n");
#将规则sql的检查结果插入明细表
my $detailInsertSql = "Insert Into ${check_detail}" .
" select ${checkID},'${RUNDATE}', ${Map_Id}," .
" '${Topic_Area}','${Sys_Id}','${table_Name}','${Check_Column_Name}','${CheckDimension}','${CheckSegmentation}',".
" ${pkselect},${Org_Column_Name},${ckselect} from ".$fromclause;
my $detailsth = $dbh->prepare($detailInsertSql) or return -1;
$detailsth->execute() or return -1;
$detailsth->finish();
print $logFile (GetNowTime() ." ************************** insert into detail end **************************\n");
print $logFile (GetNowTime() ." ************************** insert into sample data begin **************************\n");
#从临时表按照规则、机构和运行日期的维度取得样本数据,插入明细表
#partition by 可以是多个字段
my $sampInsert = "insert into ${check_detail_sample}".
" select ${checkID},'${RUNDATE}',${Map_Id},'${Topic_Area}','${Sys_Id}','${table_Name}','${Check_Column_Name}',".
"'${CheckDimension}','${CheckSegmentation}',pk_column_value,org_id,check_column_value from ".
"(select crt.*,ROW_NUMBER() over( partition by org_id,check_id) as seq from ${check_detail} crt where rundate='${RUNDATE}') detailtmp ".
" where detailtmp.seq<6";
my $inssth = $dbh->prepare($sampInsert) or return -1;
$inssth->execute() or return -1;
$inssth->finish();
print $logFile (GetNowTime() ." ************************** insert into sample data end **************************\n");
print $logFile (GetNowTime() ." ************************** begin insert check_result**************************\n");
#将样本数据插入到result表,直接通过sql进行数据的循环插入,方式insert into table select ******
my $InsSql = " Insert Into ${check_Result}".
" select ${checkID},'${RUNDATE}', '${Rule_Name}',${Map_Id},'${Topic_Area}','${Sys_Id}','${table_Name}','${Check_Column_Name}','${CheckDimension}','${CheckSegmentation}',".
" mainorg ,effectCount,effectCount-decode(FailCount,null,0,FailCount), decode(FailCount,null,0,FailCount),".
" cast(decode(FailCount,null,0,FailCount) as double)/effectCount,cast((effectCount-decode(FailCount,null,0,FailCount)) as double)/effectCount from ".
"(select count(*) as effectCount, $Org_Column_Name as mainorg from ${table_Name} where 1=1".$preWhereCluse." group by ${Org_Column_Name}) tmain ".
" left join ".
"(select count(*) as FailCount, org_id,check_id from ${check_detail} detail where detail.rundate = '${RUNDATE}'and check_id=${checkID} group by org_id,check_id) tdetail".
" on tmain.mainorg = tdetail.org_id";
my $collsth = $dbh->prepare($InsSql) or return -1;
$collsth->execute() or return -1;
$collsth->finish();
print $logFile (GetNowTime() ." ************************** end insert check_result**************************\n");
$dbh->commit();
#print (GetNowTime() ." ************************** delete temp table begin **************************\n");
#删除临时表的所有记录,采用truncate的方式
#my $deleteTmpTable = "truncate table ${check_detail_temp} immediate ";
#my $delsth = $dbh->prepare($deleteTmpTable) or return -1;
#$delsth->execute() or return -1;
#$delsth->finish();
#print (GetNowTime() ." ************************** delete temp table end **************************\n");
}#else block
}#rule_info for block
return 0;
}
sub main{
#得到数据库连接
$dbh = DBconnect();
#初始化规则组信息
print $logFile (GetNowTime() . " *********************init ruleGroup info ! ***************************\n");
getRuleGroupInfo();
#如果查询没有数据,返回接收的数组取值后,下标的最大值就是-1
my $ruleGrouplength = $#${Rule_Group}+1;
print $logFile (GetNowTime() . " *********************ruleGroup length: $ruleGrouplength ***************************\n");
#判断执行结果
if ($ruleGrouplength = 0 ){
print $logFile (GetNowTime() . " *********************No Rule_Group Info !*********************\n");
} else {
print $logFile (GetNowTime() . " *********************Get Rule_Group:Succeed !********************* \n");
}
#创建临时表
#my $createDDL = createtemptableDDL();
#my $sth = $dbh->prepare($createDDL) or return -1;
#$sth->execute() or return -1;
#$sth->finish();
#循环规则组,根据每一个规则组,找到该规则组下的规则(注意规则状态必须是1,即是可运行的)
my $groupTemp = '';
for my $i(0..$#${Rule_Group}){
$groupTemp = ${Rule_Group}->[$i]->[0];
print $logFile (GetNowTime() . "********************* Begin To Run Rule_Group[$i+1],groupId:${groupTemp}********************* \n");
#传入了规则组参数Mapid
print $logFile (GetNowTime() . " *********************Begin To get Rule Info! ***************************\n");
getRuleInfo($groupTemp);
print $logFile (GetNowTime() . " *********************end To get Rule Info! ***************************\n");
print $logFile (GetNowTime() . " *********************Begin To execute Rule check ! ***************************\n");
exeRuleSql();
print $logFile (GetNowTime() . " *********************end To execute Rule check ! ***************************\n");
}
#删除表
#my $droptable = "drop table ${check_detail_temp}";
#my $sthdrop = $dbh->prepare($droptable) or return -1;
#$sthdrop->execute() or return -1;
#$sthdrop->finish();
print $logFile (GetNowTime() . " ********************* end ***************************\n");
#关闭打开的文件流
close $logFile;
}
sub GetNowTimeNospechar{
my ($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime();
$hour = sprintf("%02d", $hour);
$min = sprintf("%02d", $min);
$sec = sprintf("%02d", $sec);
my $stime = GetNowDate().$hour.$min.$sec;
return $stime;
}
sub GetNowTime{
my ($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime();
$hour = sprintf("%02d", $hour);
$min = sprintf("%02d", $min);
$sec = sprintf("%02d", $sec);
my $stime = GetNowDate()." ".$hour.":".$min.":".$sec;
return $stime;
}
#找到当前的日期,月份要加1,年份是从1900开始算的
sub GetNowDate{
my ($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime();
$mon = sprintf("%02d", $mon+1);
$day = sprintf("%02d", $day);
my $stime = ($year+1900)."-".$mon."-".$day;
return $stime;
}
#方法调用,程序入口
main();
相关推荐
### AD电气规则检查步骤详解 #### 一、前言 在电子设计自动化(EDA)领域,Altium Designer(简称AD)是一款广泛使用的软件工具,它为电子工程师提供了强大的原理图设计、PCB布局以及信号完整性分析等功能。电气...
C Checker是一款专为C语言设计的规则检查工具,旨在提升代码质量和安全性,尤其适用于高可靠性和高安全性软件的开发过程。这款工具由航天软件评测中心研发,利用先进的编译技术和静态编码安全性分析技术,对C语言源...
Sonar-Kotlin检查规则指南 SonarQube 是一款代码分析工具,旨在帮助开发者编写高质量的代码。 Sonar-Kotlin 是 SonarQube 的一个插件,专门用于分析 Kotlin 语言项目。 Sonar-Kotlin 提供了许多内置规则,帮助...
产品一致性检查确保实际产品与认证或认可时的信息一致,而现场产品性能检测则是对产品在实际使用条件下的功能和性能进行验证。此外,还可能进行产品抽样送法定消防产品质量检验机构进行进一步检验,以确保其符合相关...
cppcheck是一款静态代码分析工具,主要用于检测C/C++代码中的潜在错误、未...通过以上步骤和知识,开发者可以充分利用cppcheck的自定义规则功能,提升代码质量,预防潜在的运行时错误,从而打造更加健壮的软件系统。
2. **术语和定义**:明确了认证技术负责人、产品一致性、例行检验、确认检验、关键件定期确认检验和功能检查等关键概念,为企业和认证机构提供了统一的理解标准。 3. **工厂质量保证能力要求**: - **职责和资源**...
该软件集成了多个功能模块,包括AI检查器、RULES武器查错、RULES建筑顺序查错以及ART检查器,每个部分都有其独特的功能和重要性。 首先,AI检查器.js是用于分析游戏中的智能体(AI)脚本的模块。在红色警戒2中,AI...
### C++Test 代码静态检查规则制作方法及实践 #### 一、引言 在团队进行软件开发过程中,制定并遵循一套共同的编码规范至关重要。这不仅有助于提高代码质量和可维护性,还能促进团队成员之间的有效沟通。然而,随着...
《消防产品现场检查判定规则汇编》是一份重要的技术文档,详细规定了对各类消防产品的现场检查、判定标准和流程,旨在确保消防设备的质量和功能,保障人民生命财产安全。以下是对该规则主要内容的详细解释: 1. **...
每个规则都包含了特定的逻辑,例如检查变量a的值是否等于1,或者对变量a进行加法和乘法运算。 测试: 101. 在规则编写完成后,通常需要进行测试以验证规则的正确性。在旗正规则引擎中,可以通过内置的测试功能运行...
在 Allegro172 版本中,DFM 规则功能可以帮助用户实时地检查设计是否符合DFM 规则,从而避免在生产过程中出现问题。这项功能能够提高设计效率和质量,缩短产品上市时间。 Allegro Design and Analysis 是一个功能...
- `-d` 和 `-f`: 分别检查指定路径是否为目录或文件,可用于限制重写规则的应用场景。 5. **服务器变量**: Apache提供了一系列预定义的服务器变量,如 `%{REQUEST_URI}`, `%{QUERY_STRING}`, `%{HTTP_REFERER}` 等...
通过设置“执行到此”功能,规则引擎会在达到指定规则时停止执行,然后检查规则包的输出结果。这种方式允许开发者逐个检查规则的效果,便于定位问题。 - 批量测试:批量测试适用于大规模数据的验证,开发者可以输入...
《消防产品现场检查判定规则》是规范消防产品质量和安全的重要标准,旨在确保消防设施的可靠性和有效性,防止因产品质量问题导致的火灾风险。本规则详细规定了消防产品的现场检查流程、标准和方法。 1. 范围:该...
可用性检查的主要功能包括:检查组、检查规则、需求传输、可用性检查计划等。检查组是指根据不同的业务需求来定义不同的检查组,每个检查组都可以有多个检查规则。检查规则是指根据不同的业务需求来定义不同的检查...
《抽样检查实施规则》是指导企业进行质量控制和质量管理的重要文档,主要涉及抽样检查的方法、适用范围和标准。以下是对该文件主要内容的详细解释: 1. **适用范围**: - 抽样检查实施规则适用于企业的内外购品的...
AD(Altium Designer)和DXP(Protel DXP)是常用的PCB设计软件,提供了强大的设计工具和规则检查功能。本篇文章将围绕"PCB设计规则检查注意事项"进行详细阐述,旨在帮助设计师们确保设计的质量。 一、布局检查 ...
Altium Designer是一款强大的PCB(印刷电路板)设计软件,其中设计规则检查(DRC)是确保设计质量的关键工具。DRC系统旨在检测并预防设计过程中可能出现的逻辑和物理问题,如过小的间距、短路或其他不符合规定的设计...